4

令人困惑的问题,我知道。鉴于以下情况:

    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 的机制?

提前致谢!

4

2 回答 2

14

除非涉及“动态”类型,否则重载决议和类型推断是在编译时执行的,而不是在运行时执行的。

当重载决议看到Test.GenericFunc(this);它必须推导出对应于缺少的泛型类型参数的泛型类型参数。这是一个简单的问题;它使用compile time类型this,并且在一个方法内部BaseType,显然compile time类型thisis always BaseType

因此重载决议假定您打算调用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.

于 2011-07-14T20:57:32.903 回答
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.

于 2011-07-14T20:51:43.967 回答