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

Bil*_*oks 4 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 { }
Run Code Online (Sandbox Code Playgroud)

以下代码生成有趣的输出:

    DerivedType Derived = new DerivedType();
    Derived.RunTest();

    // output:
    // typeof(T): BaseType
    // SomeType.GetType(): DerivedType
Run Code Online (Sandbox Code Playgroud)

但是,这表现得如我所料:

    Test.GenericFunc(new Derived());

    // output:
    // typeof(T): DerivedType
    // SomeType.GetType(): DerivedType
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮助我理解这里的机制导致T在第一种情况下被评估为BaseType吗?

提前致谢!

Eri*_*ert 14

除非涉及"动态"类型,否则在编译时执行重载决策和类型推断,而不是在运行时执行.

当重载决策看到Test.GenericFunc(this);它必须推导出与缺少的泛型类型参数相对应的泛型类型参数.这是一个容易的问题; 它使用编译时类型this,并且在方法内部BaseType,显然编译时类型this始终是BaseType.

因此,重载决议假设您打算打电话Test.GenericFunc<BaseType>(this).

如果你打算在运行时解决这个问题,你可以在C#4中做到这一点Test.GenericFunc((dynamic)this).只需说. 这将在运行时再次启动重载解析引擎,然后假装您this在编译时强制转换为其运行时类型.

是的,这听起来有点贵.如果您想在运行时进行语义分析,那么我们将不得不在运行时运行语义分析器.


Chr*_*Wue 6

因为这:

public class BaseType
{
    public void RunTest() { Test.GenericFunc(this); }
}
Run Code Online (Sandbox Code Playgroud)

基本上相当于:

public class BaseType
{
    public void RunTest() { Test.GenericFunc<BaseType>(this); }
}
Run Code Online (Sandbox Code Playgroud)

因此,GenericFunc在编译时获得实例化T = BaseType.但是,this您在运行时传入的对象是您获得的派生类型SomeType.GetType().

在第二种情况下,编译器DerivedType直接从使用中推断出类型,因此GenericFunc可以实现T = DerivedType.