令人困惑的问题,我知道。鉴于以下内容:
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 { }
以下代码产生了有趣的输出:
DerivedType Derived = new DerivedType();
Derived.RunTest();
// output:
// typeof(T): BaseType
// SomeType.GetType(): DerivedType
然而,这表现得如我所料:
Test.GenericFunc(new Derived());
// output:
// typeof(T): DerivedType
// SomeType.GetType(): DerivedType
有人能帮助我理解这里的机制导致T在第一种情况下被评估为BaseType吗?
提前致谢!
答案 0 :(得分:14)
除非涉及“动态”类型,否则重载分辨率和类型推断在编译时执行,而不是在运行时
执行。当重载决策看到Test.GenericFunc(this);
时,它必须推导出与缺少的泛型类型参数对应的泛型类型参数。这是一个容易的问题;它使用this
的编译时间类型,在BaseType
的方法中,显然this
的编译时类型是始终BaseType
。
因此,重载决议假定您打算拨打Test.GenericFunc<BaseType>(this)
。
如果您希望将其设置为运行时,则可以在C#4中执行此操作。只需说出Test.GenericFunc((dynamic)this)
即可。 这将在运行时再次启动重载解析引擎,然后假装您在编译时将this
强制转换为其运行时类型。
是的,这听起来有点贵。 如果您想在运行时进行语义分析,那么我们将不得不在运行时运行语义分析器。
答案 1 :(得分:6)
因为:
public class BaseType
{
public void RunTest() { Test.GenericFunc(this); }
}
基本上相当于:
public class BaseType
{
public void RunTest() { Test.GenericFunc<BaseType>(this); }
}
因此,GenericFunc
在编译时使用T = BaseType
进行实例化。但是,您在运行时传入的this
对象是SomeType.GetType()
得到的派生类型。
在第二种情况下,编译器直接从用法中将类型推断为DerivedType
,因此GenericFunc
将使用T = DerivedType
进行实例化。