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

本文关键字:参数 是什么 类型 泛型 this 基类 调用 使用 函数 | 更新日期: 2023-09-27 18:02:02

我知道这是个令人困惑的问题。

    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在第一种情况下?

提前感谢!

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

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

当重载解析看到Test.GenericFunc(this);时,它必须推断出与缺失的泛型类型形参对应的泛型类型实参。这是一个简单的问题;它使用this编译时间类型,并且在BaseType的一个方法中,显然this编译时间类型始终是BaseType

因此,重载解析假定您打算调用Test.GenericFunc<BaseType>(this)

如果你想在运行时解决这个问题,你可以在c# 4中这样做。就说Test.GenericFunc((dynamic)this)吧。这将在运行时再次启动重载解析引擎,然后它将假装您在编译时将this转换为其运行时类型。

是的,那和听起来一样贵。如果你想在运行时进行语义分析,那么我们必须在运行时运行语义分析器

因为:

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,因此GenericFuncT = DerivedType初始化。