Charles Churchill wrote:
I apologize if this question has been asked before, but after about
half an hour of searching I haven't been able to find an answer online.
My code is beloiw, with comments pertaining to my question
In short my question is why when I pass a generic type directly to the
formatObject function it works fine, but when I pass it to the
checkText function where it is itself a generic argument, and then it
is passed to formatObject, it is seen as an Object and not as the type
it is? Any help would be greatly appreciated.
Here are the relevant sections of my code (I apologize for any typos as
the actual code is on a remote system that I cannot cut and past from)
public class FormatObject
{
public static string formatObject(Object o)
{
return o.ToString();
}
public static string formatObject<K,V>(KeyValuePair<K,Vkvpo)
{
//do some reflectiony sort of things to build up string
// that looks like (KeyValuePair<Int32, Int32= {10,10})
message += formatObject(kvpo.Key);
// call formatObject on the key and value
// recursively in case they are of a type handled
// by other formatObject calls
return message
}
// a few other overridden formatObject functions taking different
// types (List<T>, List<List<T>>, etc)
}
public class CheckText
{
public bool void checkText(T t, string matchPattern)
{
string ostr;
ostr = FormatObject.formatObject(t);
return (ostr.IndexOf(matchPattern) != -1)
}
}
public void Main(string[] args)
{
KeyValuePair<int, intk = new KeyValuePair<int, int>(10,.10);
string formatted = FormatObject.formatObject(k);
// Calls the appropriate function and returns a string consisting of
// (KeyValuePair<Int32, Int32= {10,10})
bool doesContain = CheckText.checkText(k,"(KeyValuePair");
// returns false as it calls the Object overriden version
// of formatObject. which returns a string
// consisting of "{10,10}"
}
I'm not using generics yet, but a couple of minutes looking at your
code leads me to believe that your problem has nothing to do with
generics, as such. Rather, it involves the following:
"Which overload of a method should be called is determined at compile
time, not run time. Method overRIDES are resolved at run time; method
overLOADS are resolved at compile time."
So, in your case, the line
ostr = FormatObject.formatObject(t);
will result in a call to FormatObject.formatObject(Object o) unless T
is a subtype of KeyValuePair<K, V>. Even if at run time the variable t
refers to an instance of a class that implements the correct interface
/ inherits from the correct class so that a call to
FormatObject.formatObject<K, Vwould be possible, it still won't
happen because the compiler has no way of knowing that that will be the
case.
Take a simpler, non-generic example:
public class Foo : IComparable
{
public int CompareTo(object other)
{
// Native Foo object greater than any other kind of object
return 1;
}
public int CompareTo(Foo otherFoo)
{
... do some stuff to compare Foos ...
}
}
public class Other
{
public static int CompareFoo(Foo aFoo, object something)
{
return aFoo.CompareTo(something);
}
}
A call such as myOther.CompareToFoo(...) will _always_ return -1. Why?
Because no matter what is passed as the argument "something", the
compiler has already determined that the correct signature to call is
Foo.CompareTo(object), based on the fact that the "something" argument
is declared as an object type. Even if you pass a Foo instance at run
time, it still calls the Foo.CompareTo(object) method.
The usual way around this is to do the testing yourself, at run time,
to determine whether the more specific method is appropriate:
public int CompareTo(object other)
{
Foo otherFoo = other as Foo;
if (otherFoo != null)
{
return this.CompareTo(otherFoo);
}
else
{
// Native Foo object greater than any other kind of object
return 1;
}
}
.... or something like that.
In your case, you need to test, within formatObject(object o) whether
"o" is an instance of something that could be passed to the generic
method, and then call the generic method if appropriate.
Maybe. As I said, I'm not on V2.0 yet. :-)