从具有'this'的基类调用时,泛型函数参数的参数类型是什么?

时间:2011-07-14 20:46:16

标签: c# inheritance generic-function

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

    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吗?

提前致谢!

2 个答案:

答案 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进行实例化。