C# 使用哪个好:Object.GetType()==typeof(Type)或Object是Type?

C# 使用哪个好:Object.GetType()==typeof(Type)或Object是Type?,c#,performance,types,C#,Performance,Types,我想知道,从性能的角度看,哪条语句有用,是否使用 Object.GetType() == typeof(Type) 或 第二条: Object is Type 使用string和int测试了这1'000'000'000次,得到: //Release 00:00:18.1428040 //Object.GetType() == typeof(Type) 00:00:03.9791070 //Object is Type //Debug 00:00:21.3545510 //Object.Get

我想知道,从性能的角度看,哪条语句有用,是否使用

Object.GetType() == typeof(Type)

第二条:

Object is Type
使用
string
int
测试了这1'000'000'000次,得到:

//Release
00:00:18.1428040 //Object.GetType() == typeof(Type)
00:00:03.9791070 //Object is Type
//Debug
00:00:21.3545510 //Object.GetType() == typeof(Type)
00:00:06.2969510 //Object is Type
//Machine specs:
//Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
//6 GB RAM memory
//Ubuntu 14.04 (OS)
//Runtime: Mono JIT compiler version 3.2.8
//Compiler: Mono dmcs
//Notes: ran these with some background processes, but the difference in time
//       is significant enough I guess.
注意:两者之间存在强烈的语义差异

  • 相等性
    ==
    检查类型相等性:换句话说,如果
    A:B
    对于
    A.GetType()==typeof(B)
    A是B
    将成功
  • 如果对象为
    null
    ,它将抛出
    System.NullReferenceException
    。在第二种情况下,它将返回
    false
从编译器的角度来看,这是一种逻辑:在第一个变量中,查询对象的类型。如果这不是真正优化的,则首先执行函数调用,然后该调用表示必须返回指向类型表的指针

在第二种情况下,您省略了这样的调用:编译器将通过返回类型代码来专门化它。如果预先知道
类型
,它甚至可以对其进行非常快速的测试

此外,请注意,对于一些简单的情况,
对象是类型
可以优化的:例如,因为编译器已经可以派生出
对象
不能/总是类型为
类型

更高级

还可以分析CIL虚拟机源代码,对于第一个变体,这是:

IL_0000: ldarg.0
IL_0001: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0006: ldtoken [mscorlib]System.Int32
IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0010: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type)
IL_0015: ret
对于第二种变体,这是:

IL_0000: ldarg.0
IL_0001: isinst [mscorlib]System.Int32
IL_0006: ldnull
IL_0007: cgt.un
IL_0009: ret
(当然,您可以填写其他类型)。现在
ldarg.0
ret
只是使用方法的副产品,因此可以忽略它们

我们看到的是,在第一个变量中,显式调用
GetType
方法,然后调用
==
操作符。函数调用通常是昂贵的。在第二个变量中,它会立即检查
isinst
。代码需要更少的字节,并且使用更便宜的方法。虽然性能当然取决于运行时环境的实现,但我认为可以肯定地说,第二种变体在性能上几乎总是优于第一种变体


编译器可能会对第一个变量进行专门化,使其与第二个变量一样高效运行,但Mono C#编译器似乎无法做到这一点。可能所有可用的C#编译器都不会。

重要的是要理解这两个编译器是不等价的,在处理继承或接口时,一个会返回false,另一个会返回true。Bharadwaj的链接问题演示了这些差异。您可以自己实际测试。@t3chb0t:测试确实可以给出指示,但正如您所看到的,答案也提供了一个解释:
的专用CIL指令是
,而
的.GetType()是=
是通过执行昂贵的函数调用来解决的。@AmolBavannavar:这是为了让其他用户有机会想出更好的答案。对于这样的问题,很有可能。你用测试测量在四分钟内回答了这个问题?太不可思议了;-)@阿列克谢列文科夫:修改,更好?公平-我添加了链接到这个的评论。。。删除不相关的评论30…29..这个答案与一个答案不矛盾吗,说的恰恰相反?
IL_0000: ldarg.0
IL_0001: isinst [mscorlib]System.Int32
IL_0006: ldnull
IL_0007: cgt.un
IL_0009: ret