22

I want to know that which statement is useful from a Performance Point of View whether to use

Object.GetType() == typeof(Type)

or

Object is Type
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Amol Bavannavar
  • 2,062
  • 2
  • 15
  • 36
  • 4
    http://stackoverflow.com/questions/983030/type-checking-typeof-gettype-or-is?rq=1 – Bharadwaj Jan 07 '15 at 06:09
  • 4
    It's important to understand these two are not equivalent and when dealing with inheritance or interfaces, one will return false and the other true. Bharadwaj's linked question demonstrates these differences. – AaronLS Jan 07 '15 at 06:13
  • 1
    You can have actually tested this by yourself. – t3chb0t Jan 07 '15 at 06:30
  • 2
    @t3chb0t: tests can indeed give an indication, but as you can see, the answer also provides an explanation: there exist dedicated CIL instructions for `is` whereas the `.GetType() == ` is resolved by performing expensive function calls. – Willem Van Onsem Jan 07 '15 at 06:32

1 Answers1

52

The second one:

Object is Type

Tested this 1'000'000'000 times with string versus int one gets:

//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.

Note: There is a strong semantic difference between the two:

  • The equality == checks on type equality: in other words, if A : B than the equality test will fail for A.GetType() == typeof(B) whereas A is B will succeed.
  • If the object is null, it will throw a System.NullReferenceException. In the second case, it will return false.

This is rather logic from a compiler point-of-view: in the first variant, you query the object for its type. In case that's not really optimized, you do a function call first, that call then says it must return a pointer to the type-table.

In the second case, you omit such calls: the compiler will specialize it by returning the type-code. And if the Type is known in advance, it can even work out a very fast test for it.

Note furthermore that for some trivial cases, Object is Type can be optimized: for instance because the compiler can already derive that Object can't/is always of type Type.

More advanced

One can also analyze the CIL virtual machine source code, for the first variant, this is:

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

For the second variant this is:

IL_0000: ldarg.0
IL_0001: isinst [mscorlib]System.Int32
IL_0006: ldnull
IL_0007: cgt.un
IL_0009: ret

(you can of course fill in other types). Now the ldarg.0 and ret are simply by-products of using a method, so one can ignore them.

What one sees is that in the first variant, one calls the GetType method explicitly and then calls the == operator. Function calls are in general expensive. In the second variant, it checks immediately for isinst. The code requires less bytes and uses less expensive methods. Although performance of course depends on the implementation of the runtime environment, I think it's rather safe to say the second variant will nearly always beat the first one on performance.

A compiler could probably specialize the first variant such that it runs as efficient as the second, but the Mono C# compiler doesn't seem to do this. Probably none of the available C# compilers will.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555