The case of typeof, TypeHandle, Type.Equals, and the mysterious RuntimeTypeHandle

Here’s a .NET performance enhancing trick that’s worth keeping up your sleeve.

Sometimes the logic of a function or process entails the use of the typeof operator as a means of deciding what to do, or what not to do. For example:

Type t = myInstance.GetType();

if(typeof(foo).Equals(t))

{

this.DoSomething();

}

Now, this is not a poor use of resources and processor time. It is a perfectly valid thing to do, when it is the thing to do! However, there is a better way. In fact, move the same logic into a loop, because it is used to decide what to do with each element of a collection, and voila, you have a performance hog and and a time-waster on your hands that begs for a better way!

This blog post is about simply that; when using type equality repetitively, as in the case of a looping statement, or even when you know you will compare known types more than once in the lifetime of an instance. The following guidelines should apply:

  • Never use typeof more than once for the same type within the same scope.
  • Do not perform multiple type comparisons, using the same type, more than once.

Take a look at this example of how we might find ourselves in such a situation. It may not be a real situation, but I will try to use it to highlight the potential for a performance issue:

foreach(object foo in someThings)

{

if(foo.GetType().Equals(typeof(Foo)))

{

this.DoSomething();

}

}

Now there is simply no excuse for the code above to use typeof within the loop. I repeat: It is inexcusable! Of course you must use typeof only once, outside the loop! As follows:

Type t_Foo = typeof(Foo);

foreach(object foo in someThings)

{

if(foo.GetType().Equals(t_Foo))

{

this.DoSomething();

}

}

OK, fine, now it is more efficient, but hey, this is pretty basic stuff…like I said OF COURSE you do  it the latter way, rather than the former! Now that the obvious is certainly out of the way though, there still remains the not so obvious: using the Equals, or == operator (the ‘==’ likely ends up as a call to Equals under the hood anyways, use .net reflector to see for yourself…) on a type is an expensive thing to do, furthermore, it is unnecessary.

So…an unnecessary, expensive thing…well, it might seem perfectly acceptable to have many expensive and unnecessary things in our homes, but we should not have them where our code lives! This, is where TypeHandle, and RuntimeTypeHandle come into play…

The Equals operator used in the example above will compare a Type with a Type.

TypeHandle and RuntimeTypeHandle, allow us to achieve the same comparison at a fraction of the cost! Observe the difference in the following example:

private static readonly RuntimeTypeHandle handle_Foo;
static MyType()
{
handle_Foo = typeof(Foo).TypeHandle;
}

foreach(object foo in someThings)
{
if(foo.GetType().RuntimeTypeHandle.Equals(handle_Foo))
{
this.DoSomething();
}
}

As you can see, we will still know if foo is Foo…but we will only compare what amounts to a pointer or native integral type, rather than comparing two whole instances of Type.

Now that we have established that it is OF COURSE obvious, to do it one way, rather than the other, you will OF COURSE only do it the more efficient way forevermore.

Why you might say…why care so darn much about the idiosyncrasies surrounding the potentially obscure use of some comparison operator and the possible alternatives therein? Why bother with what probably amounts to only a few milliseconds of saved time and kilobytes of memory in the lifetime of an instance? Well…I won’t try to convince you with some example of how expectations concerning projected resource use can be proven very wrong in very short order, or how we cannot forsee what might happen etc. etc, blah, blah…No, rather I will just say what my absolute conviction on the matter is: What sets those who become experts in their field apart from the crowd IS that they just do care about such things, because they cannot help but remember, once they know. It is also an attitude, a frame of mind, a work ethic. Whatever you call it, I think it is the difference between messing around and maybe making a mess, and playing hard and maybe going for gold! The thrill after all, is not the catch…it’s the chase! 🙂

Happy coding!