Which is good to use: Object.GetType() == typeof(Type) or Object is Type?

c#, performance, types

Solution

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.

Problem

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 ```

Original source

Related problems