在使用泛型时,对象的类型是什么时候以及如何确定的,特别是当泛型类型被约束到类并且泛型类型是隐式的时候?
为了清楚起见,给出了以下代码:
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)
返回基类的名称,而不是派生类的名称?我猜这个调用隐式地解析为基于变量myClass
的声明类型的GetMyClassTypeByGenericType<MyClass>(myClass)
,而不是实际的类型。
基本上,我只想知道关于类型如何确定的泛型背后发生了什么。
下面是代码的小提琴:https://dotnetfiddle.net/pCj08M
发布于 2018-08-02 20:50:52
泛型类型解析完全是编译时(这就是为什么你不能在泛型类型参数中填充一个没有反射的Type
变量,这并不是我们真正在讨论的问题)。
因此,当给定一个变量类型MyClassA
时,它就会使用这个变量类型。对于MyClass
也是如此,即使实际对象是派生类型。例如,如果您将其保存在object
引用中,则第一个调用将打印System.Object
。
另一方面,GetType
是运行时,所以它获得对象的实际类型,而不管保存它的变量的类型是什么。
发布于 2018-08-02 20:52:47
泛型类型构造,即解析每个泛型类型参数的实际类型的过程,总是在C#中的编译时执行(当然,除非您正在使用Reflection API。
在您的示例中,编译器根据传递给该方法的参数的静态类型推断T
类型。myClass
的静态类型和你声明的完全一样:MyClass
,所以当你在泛型方法中检查T
时,你会发现这个T == typeof(MyClass)
。
另一方面,当您对传入的对象调用.GetType()
时,您正在对该对象的动态(实际运行时)类型进行运行时查询,这当然就是您构造的MyClassA
。
https://stackoverflow.com/questions/51661896
复制相似问题