是否有人知道typeof(T) where T : struct
之间存在任何差异,
例如,与t.GetType() where t is a System.Object
?
ILdasm显示typeof(T)使用System.Type::GetTypeFromHandle(RuntimeTypeHandle handle)
,另一个只是普通System.Object::GetType()
。实现是[MethodImpl(MethodImplOptions.InternalCall)]
,
所以这些方法是在CLR中的本机代码中定义的。所以,我只是想知道是否有人知道任何理由更喜欢一个而不是另一个?
答案 0 :(得分:44)
typeof
实例,则使用 Type
。 GetType
给出了调用它的对象的运行时类型,它可能与声明的类型不同。
例如:
class A {}
class B : A {}
class Program
{
static A CreateA()
{
return new B();
}
static void Main()
{
A a = CreateA();
Console.WriteLine(typeof(A)); // Writes "A"
Console.WriteLine(a.GetType()); // Writes "B"
}
}
在上述情况下,在Main
方法中,您处理的是A
类型的实例;因此,如果您关心声明的类型,则使用typeof(A)
。但是,CreateA
方法实际上返回派生类B
的实例,尽管将基类声明为返回类型。如果要查找有关此运行时类型的信息,请在返回的实例上调用GetType
。
编辑:Mehrdad的评论指向了正确的方向。虽然typeof
发出GetTypeFromHandle
调用,其中RuntimeTypeHandle
作为参数,但所述参数实际上对应于其元数据令牌位于评估堆栈上的特定类型。在某些情况下,此标记将隐式存在(由于当前方法调用);否则,可以通过调用ldtoken明确地将其推送到那里。您可以在这些答案中看到更多这方面的例子:
编辑 2 :如果您正在寻找效果基准,可以参考Jon Skeet's answer。他的结果是:
typeof(Test): 2756ms
test.GetType(): 3734ms
答案 1 :(得分:4)
好吧,有时候在通用代码中,你知道类型参数T
的编译时类型,而没有实例。然后,您必须使用typeof(T)
。
在其他时候,通常在非通用代码中,您可能对对象的运行时类型感兴趣。然后使用GetType()
。
因此,在某些情况下,根据您想知道的内容或您可以查询的内容,您只有一个选项。
有时候,你可以选择。
答案 2 :(得分:3)
如果需要编译时信息,可以使用typeof;当需要运行时信息时,可以使用GetType。
如果您处于可以使用其中任何一种的情况,则应使用typeof,因为它可以在编译时解析。这使得类型值更清晰,并且(原则上)允许更多优化。
typeof关键字采用编译时类型标识符,并为您提供Type:
的相应运行时实例Type intType = typeof(int);
Type stringType = typeof(string);
Type objectType = typeof(object);
Type genericType = typeof(T);
// not permitted: typeof(1), typeof(someVariable)
GetType实例方法采用运行时实例并告诉您其确切的运行时类型:
Type intType = 1.GetType(); // typeof(int)
Type objectType = new Object().GetType(); // typeof(object)
object x = "test";
Type stringType = x.GetType(); // typeof(string), NOT typeof(object)
// not permitted: int.GetType(), string.GetType(), T.getType()
在编写反射函数,手工创建表达式树或使用可怕的Enum方法(使用Type实例而不是泛型类型参数)时,通常只需要使用typeof或GetType。
答案 3 :(得分:2)
GetType()
用于检索实际拥有的实例类型,但typeof()
用于获取实例类型,而GetType()
在运行时得到typeof()
,而{ {1}}在编译时解析。