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

时间:2015-01-07 06:01:23

标签: c# performance types

我想知道哪个语句在 Performance Point of View 中是否有用

Object.GetType() == typeof(Type)

Object is Type

1 个答案:

答案 0 :(得分:41)

第二个:

Object is Type

使用stringint进行了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 is B将会成功。
  •   
  • 如果对象为null,则会抛出System.NullReferenceException。在第二种情况下,它将返回   false
  •   

这是编译器视点的逻辑:在第一个变体中,您查询对象的类型。如果没有真正优化,你先做一个函数调用,然后调用它说它必须返回一个指向类型表的指针。

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

此外,请注意,对于某些微不足道的情况,Object is Type可以进行优化:例如,因为编译器已经可以推导出Object不能/始终是Type类型。

更高级

还可以分析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.0ret只是使用方法的副产品,因此可以忽略它们。

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

编译器可能专门化第一个变体,使其运行效率与第二个变量一样高,但Mono C#编译器似乎不会这样做。可能没有可用的C#编译器。