当隐式类型为隐式泛型时,何时以及如何确定类型?

时间:2018-08-02 20:44:25

标签: c# generics inheritance implicit-conversion

使用泛型时,何时以及如何确定对象的类型,特别是当泛型类型被约束到一个类而泛型类型是隐式的时?

为了澄清,给出以下代码:

public class MyClass {}
public class MyClassA : MyClass {}

public static string GetMyClassTypeByGenericType<T>(T myClass)
    where T: MyClass
{
    return typeof(T).Name;
}

public static string GetMyClassTypeByObjectType<T>(T myClass)
    where T: MyClass
{
    return myClass.GetType().Name;
}

MyClassA myA = new MyClassA ();
GetMyClassTypeByGenericType(myA); // Result: "MyClassA"
GetMyClassTypeByObjectType(myA); // Result: "MyClassA"

MyClass myClass = myA;
GetMyClassTypeByGenericType(myClass); // Result: "MyClass"
GetMyClassTypeByObjectType(myClass); // Result: "MyClassA"

为什么调用GetMyClassTypeByGenericType(myClass)返回基类的名称,而不返回派生类的名称?我猜想该调用将根据变量GetMyClassTypeByGenericType<MyClass>(myClass)的声明类型而不是实际类型隐式地解析为myClass

基本上,我只想知道泛型到底是如何确定类型的。

这里是代码的小提琴:https://dotnetfiddle.net/pCj08M

2 个答案:

答案 0 :(得分:2)

泛型类型解析全部是编译时间(这就是为什么您不能在没有反射的情况下将Type变量填充到泛型类型参数中的原因,这实际上不是我们在这里谈论的内容)。

因此,当给定变量类型MyClassA时,将使用它。对于MyClass同样,即使实际对象是派生类型。例如,如果您将其保存在object引用中,则第一个调用将显示System.Object

另一方面,GetType是运行时,因此无论对象的变量类型是什么,它都会获得对象的 actual 类型。

答案 1 :(得分:1)

泛型类型构造(解析每个泛型类型参数的实际类型的过程)始终在C#的编译时执行(当然,除非您使用Reflection API在以下位置构造泛型)运行时)。

在您的示例中,编译器根据传递给方法的参数的 static 类型来推断类型TmyClass的静态类型正是您声明的静态类型:MyClass。因此,当您使用通用方法检查T时,您会发现T == typeof(MyClass)

另一方面,当您对传入的对象调用.GetType()时,您正在对对象的动态(实际运行时)类型进行运行时查询,这当然是您构造的{ {1}}。