A little story about .GetType()

Last week I was writing some code with a co-worker and a line of code similar to the following came up:

if (object.GetType() == typeof(T))
{
	// ... more code here.
}


The question came up, “doesn’t this use Reflection”?  My response was that the .GetType() method itself doesn’t use reflection, but instead evaluates the object’s metadata from the CLR at runtime and produces the relevant type information.

Then, I ran across this from TweetDeck today:

To the guy ("who is always right") that said GetType() doesn't use reflection: http://msdn.microsoft.com/en-us/library/ms173183(VS.80).aspx

Now, let’s not kid ourselves here, I’m certainly not the guy who is always right.  So, ready and willing to be wrong I started reading the rather innocuous post from MSDN on the subject:

Here's a simple example of reflection using the static method GetType - inherited by all types from the Object base class - to obtain the type of a variable:

C#

// Using GetType to obtain type information:
int i = 42;
System.Type type = i.GetType();
System.Console.WriteLine(type);
 

Indeed, MSDN does say that invoking .GetType() is an example of using Reflection.  My original comment that .GetType() didn’t use Reflection was based on my (inaccurate) definition of reflection – that an object is reflected upon when it becomes loaded into memory for the sole purpose of achieving this reflection.  I suppose the difference is one of perception, really, but here it’s clearly caused confusion.

Then I ran across this post supporting my assertion, that calling .GetType() in fact constructed the type information at runtime directly using a hook into the CLR.  Is this the same as reflection?  My original point that this wasn’t reflection was really one more of performance than the syntax.  I wonder what Ritchie Swann would say now regarding his original comments on the matter:

As for how it works - the GetType() function is marked with the special attribute [MethodImpl(MethodImplOptions.InternalCall)]. This means its method body doesn't contain IL but instead is a hook into the internals of the .NET CLR. In this case, it looks at the binary structure of the object's metadata and constructs a System.Type object around it.

The question of performance, in my mind, can really only be answered by doing a comparative analysis.  How much work does .GetType() do anyway, and is it the same as other methods of Type checking?  I decided to check it out.  Consider the following rather simple class:

namespace TypeReferenceChecking
{
    class Program
    {
        static void Main(string[] args)
        {
            TestIs();
            TestGetTypeIs();
            TestGetTypeEquals();
        }

        static bool TestIs()
        {
            var newObject = new SampleType();

            return newObject is SampleType;
        }

        static bool TestGetTypeIs()
        {
            var newObject = new SampleType();

            return newObject.GetType() is SampleType;
        }

        static bool TestGetTypeEquals()
        {
            var newObject = new SampleType();

            return newObject.GetType() == typeof(SampleType);
        }
    }

    class SampleType
    {
    }
}

Looking at the disassembled C# source for this assembly with Reflector, you’ll see the following:

internal class Program
{
    // Methods
    private static void Main(string[] args)
    {
        TestIs();
        TestGetTypeIs();
        TestGetTypeEquals();
    }

    private static bool TestGetTypeEquals()
    {
        SampleType newObject = new SampleType();
        return (newObject.GetType() == typeof(SampleType));
    }

    private static bool TestGetTypeIs()
    {
        new SampleType().GetType();
        return false;
    }

    private static bool TestIs()
    {
        SampleType newObject = new SampleType();
        return (newObject != null);
    }
}

At first glance, it appears that calling .GetType() in your code, in fact, calls the runtime method .GetType(), which MSDN says is reflection.  But what about the argument that .GetType() retrieves information from the CLR hooks itself, not from an image of the assembly containing the type.  I was dying to find out, so I used Reflector on the .GetType() method itself:

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public extern Type GetType();

Sure enough, it’s exactly what Ritchie Swann eluded to.  Then I started thinking about the real question.  If .GetType() gets type information from the CLR and constructs a new instance of System.Type, how expensive is that construction? 

[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
protected Type()
{
}

It would be lovely to say that we get more answers here, but we don’t.  There is a static constructor on Type that initializes empty types, filters, etc. but no instance constructor.

So, the million dollar question, that really only Microsoft can say is:

For purposes of evaluating type comparison, is using .GetType() for an object that’s already in memory at runtime the same as evaluating type information from a type that’s not already loaded in memory?  If not, do you call both reflection?  This was the distinction that I really wanted to make the other day in my conversation with my coworker, that doing this runtime check is harmless and doesn’t cause excess work for the CLR (despite what it may be called).

I look forward to some great chats at TechEd with folks who will likely gladly weigh in.  Got your own opinion?  Comment below.

Comments (5) -

RL
RL
5/22/2010 3:02:53 AM #

My view is that we shouldn't need to dig so deep to determine what the cost of using GetType() is.  I wish this was better documented.  Hopefully Microsoft does weigh in.

Good post.

R. Lawson
R. Lawson
5/22/2010 3:29:03 AM #

At the time of our conversation I didn't think GetType() used reflection either.  I was speaking figuratively - it was returning type information and in my mind that is in the generic category of reflection, no matter what operations occur under the covers.

Then on Wednesday when going through my list of "everything I think Brandon Kelly was wrong about" I remembered that discussion and decided to look it up.

I can keep tweeting the list if it will prompt more blog entries like this Smile  

Ivory Lafuze
Ivory Lafuze
5/25/2010 10:24:34 AM #

Wow, i cant believe every other blog out there is filled up with lots of spam, can you guys do something about this? Just wanted to say you have a nice blog, what are you using for combating comment spam?

brandon
brandon
5/25/2010 4:33:49 PM #

Thanks for your comments

Shannon McMillan
Shannon McMillan
6/3/2010 5:28:41 AM #

Great post and I think it's all about what people consider reflection.

Comments are closed

About the author

I'm your host, Brandon Kelly.  I'd like to thank you for taking the time to read some of my thoughts on software develoment, the technology industry and the Florida developer community.

Month List

On My Blog

Recent Comments

Comment RSS