Overloading with generics. Is the behavior expected?
Possible duplicate:
Problem with overloading generic methods
Here's a simple code:
static class Example
{
static int DoIt(object o) { return 0; }
class A { }
static int DoIt(A a) { return 1; }
static int CallDoIt<X>(X x) { return DoIt(x); }
static void Main()
{
var a = new A();
System.Console.WriteLine(DoIt(a)); // returns 1 (as desired)
System.Console.WriteLine(CallDoIt(a)); // returns 0
}
}
The result looks very strange: the called DoIt () function calls the direct value from the case when it is called from another function. Is the behavior expected in C #? If so, how to achieve the desired behavior (preferably without reflection)?
source to share
This is the expected behavior, knowing that the type X
does not extend to the function CallDoIt
. The overload DoIt
called from CallDoIt
is statically determined based on the type of the argument X
. Since it X
can be anything, the best (and only) candidate is DoIt(object)
.
You can work around this behavior by deferring the dispatch DoIt
until it works dynamically:
static int CallDoIt<X>(X x) { return DoIt((dynamic)x); }
Another alternative is to provide a more specific version CallDoIt
:
static int CallDoIt(A a) { return DoIt(a); }
source to share
Calling a method DoIt(x)
inside a method CallDoIt<X>(X x)
should work for any type X
, so the C # compiler decided to use an overload DoIt(object o)
. If you constrain type X
to type A
like this:
static int CallDoIt<X>(X x) where X : A { return DoIt(x); }
Then the C # compiler will know that it can choose to overload DoIt(A a)
, since the type X
will always be inferred from the type A
. This also answers your second question on how to achieve the desired behavior.
source to share
Yes, this is expected behavior. The generic method is compiled once for all possible arguments. During this single compilation, DoIt(x)
it cannot be resolved before DoIt(A)
, so it is DoIt(object)
, and it will be.
You can check the object type dynamically, or better yet, have the .NET Framework for you:
static int CallDoIt(object x) { return DoIt((dynamic)x); }
Note that there is no benefit to creating a CallDoIt
generic here: it will do the same as this version. This means what CallDoIt((object)a)
is calling DoIt(A)
, not DoIt(object)
.
source to share