I ran across this code during some debugging.
private bool HasBaseType(Type type, out Type baseType)
{
Type originalType = type.GetType();
baseType = Get
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
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
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.