What does GetType() return on an instance of Type?
Asked Answered
M

3

1

I ran across this code during some debugging.

private bool HasBaseType(Type type, out Type baseType)
{
    Type originalType = type.GetType();
    baseType = GetBaseType(type);
    return baseType != originalType;
}

My initial thought was that type.GetType() in the first line of the method would always yield the equivalent of typeof(System.Type), which appears really pointless to me in context. However, MSDN suggests that Type overrides the version of GetType() that would be inherited from Object. Then, the actual MSDN page on non-static Type.GetType() (not to be confused with the three static versions) says that the GetType() method returns "The current Type." No further relevant explanation is given.

So, is the value of originalType in the method above equal to type or to typeof(System.Type)? I'm not quite sure from the documentation. If originalType is equivalent to type, would it be a copy of type so that, if the GetBaseType method alters its parameter, originalType would still be equivalent to type in its original form no matter what happens inside GetBaseType?

Malley answered 2/11, 2011 at 23:51 Comment(3)
private bool HasBaseType(Object instance, out Type baseType)Hibernaculum
If all you want is the base type why not just use the Type.BaseType property?Dichromatic
@tkeE2036 I didn't write this code; I just found it while debugging. And, believe me, there's (sadly) a lot more where this came from.Malley
S
7

1.

GetType is not defined as virtual and therefore cannot be overriden. System.Type doesn't override object's GetType, it hides it (in C# it would be represented with the new keyword). If you use a disassembly tool such as ILSpy, you'll see that it's implemented as follows:

public new Type GetType()
{
    return base.GetType();
}

As you can see it only calls the implementation of GetType of the base class (which is object), therefore the end result is the same. This version of GetType provides a formal implementation to the _Type interface. You typically don't have to worry about this interface, it's there for interoperability reasons.

2.

The GetType method is defined in object and returns System.Type. But a closer look at System.Type reveals that it's defined as abstract, hence it can never be instantiated. So the way to get something concrete from GetType is to get another type, which derives from System.Type. And indeed what we get is an instance of System.RuntimeType, which derives from System.Type.

The reason for that is that there must be only one instance that represents a given type. That is, it doesn't matter how many different instances of string (for example) you invoke GetType on, you'll still get the exact same instance, because there is only one instance that describes a string. To ensure that there is only one instance, System.Type was defined as abstract so it cannot be instantiated by user code and System.RuntimeType was defined as internal, so it's only accessible to code within mscorlib and also cannot be instantiated by user code.

3.

The existence of System.RuntimeType is an implementation detail that may be in most cases ignored. For all intents and purposes your code can assume that GetType returns an instance of System.Type. The only exception is with the following code (you can replace string with any other type):

bool b = 
    typeof(string).GetType() == typeof(Type);

If unaware of System.RuntimeType, one would assume that b would be true because it's assumed that GetType returns System.Type, which is clearly the value of the right hand expression. But since the left hand value is in fact System.RuntimeType, b is false (System.Type and System.RuntimeType are two different types and therefore aren't equal). This is the only case in which you need to be aware of System.RuntimeType to understand why the code behave as it does. In any other case, it just doesn't matter that GetType returns System.RuntimeType and you can ignore it.

4.

Here is a direct link to the part of my .NET online course that discusses Runtime Type Information (RTTI). I don't mention System.RuntimeType because like I said it's an implementation detail that can for the most part be ignored. But this link will give you more background and clearer understanding of System.Type.

http://motti.me/tw

I hope this helps!

Motti

Subaudition answered 3/11, 2011 at 3:52 Comment(0)
F
3

The Type of a Type instance is System.RuntimeType.

    {
        Console.WriteLine(typeof(System.Type).GetType());
        Console.WriteLine(typeof(string).GetType().GetType());
        Console.WriteLine(typeof(int).GetType());
        Console.WriteLine(typeof(List<int>).GetType());
    }

System.RuntimeType 
System.RuntimeType 
System.RuntimeType 
System.RuntimeType
Flee answered 3/11, 2011 at 0:14 Comment(0)
T
2

It looks like neither. When you call GetType on a Type instance, it seems to always return RuntimeType.

I checked this against the System assembly by running this code snippet:

Assembly
  .GetAssembly(typeof(int))
  .GetTypes()
  .Where(type => type.GetType() == type)

Edit: As Luke clarified in comments, the "original type" is only actually the original type when given a RuntimeType - it doesn't work for anything else. And since that type is internal to system, the method seems simply wrong.

Trici answered 3/11, 2011 at 0:11 Comment(2)
So, if an instance of System.RuntimeType was passed into the OP's method then originalType would indeed be equal to type. In all other cases they wouldn't be equal.Denier
@Denier Right on. Mind if I edit to include that clarification?Trici

© 2022 - 2024 — McMap. All rights reserved.