Confusing question, I know. Given the following:
class Test
{
public static void GenericFunc<T>(T SomeType)
{
System.Console.WriteLine("typeof(T): " + typeof(T).Name);
System.Console.WriteLine("SomeType.GetType(): " + SomeType.GetType().Name);
}
}
public class BaseType
{
public void RunTest() { Test.GenericFunc(this); }
}
public class DerivedType : BaseType { }
The following code produces interesting output:
DerivedType Derived = new DerivedType();
Derived.RunTest();
// output:
// typeof(T): BaseType
// SomeType.GetType(): DerivedType
However, this behaves as I would expect:
Test.GenericFunc(new Derived());
// output:
// typeof(T): DerivedType
// SomeType.GetType(): DerivedType
Can anyone help me understand the mechanism here that's causing T to be evaluated as BaseType in the first case?
Thanks in advance!
Because this:
public class BaseType
{
public void RunTest() { Test.GenericFunc(this); }
}
Is basically equivalent to:
public class BaseType
{
public void RunTest() { Test.GenericFunc<BaseType>(this); }
}
Therefore the GenericFunc
gets instatiated at compile time with T = BaseType
. However the this
object you are passing in at runtime is the derived type which you get by SomeType.GetType()
.
In the second case the compiler infers the type as DerivedType
directly from the usage and therefore GenericFunc
gets instatiated with T = DerivedType
.
Unless the "dynamic" type is involved, overload resolution and type inference are performed at compile time, not at run time.
When overload resolution sees Test.GenericFunc(this);
it must deduce the generic type argument that corresponds to the missing generic type parameter. That is an easy problem; it uses the compile time type of this
, and inside a method of BaseType
, clearly the compile time type of this
is always BaseType
.
Therefore overload resolution assumes that you intended to call Test.GenericFunc<BaseType>(this)
.
If you intend this to be worked out a runtime, you can do that in C# 4. Just say Test.GenericFunc((dynamic)this)
. That will start the overload resolution engine again at runtime, which will then pretend that you had cast this
to its runtime type back at compile time.
Yes, that is every bit as expensive as it sounds. If you want semantic analysis at runtime then we're going to have to run a semantic analyzer at runtime.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With