98

I was trying to do some convention tests today, and getting all the types in an assembly (by calling Assembly.GetTypes()), when I stumbled into something:

System.RuntimeType:[First.Namespace.FirstClass]

Whenever I try to compare that type with typeof(FirstClass), they're not equal. So, when I try to find all the types that contain FirstClass as a generic parameter, I'm not finding any.

What's the difference between System.RuntimeType and System.Type?

Is there any way to solve my problem?

Pierre Arnaud
  • 10,212
  • 11
  • 77
  • 108
Edgar Gonzalez
  • 1,862
  • 1
  • 15
  • 19

3 Answers3

120

System.RuntimeType is a concrete class that derives from the abstract base class System.Type. Since System.RuntimeType is not public, you will typically encounter instances of it as System.Type.

Confusion can arise when you are trying to get the type of an object and mistakenly call GetType() on another object representing the first object's type, rather than just using that object directly. Then Type.ToString() will return "System.RuntimeType" when the object it is called on is representing a Type:

string str = string.Empty;
Type strType = str.GetType();
Type strTypeType = strType.GetType();
strType.ToString();     // returns "System.string"
strTypeType.ToString(); // returns "System.RuntimeType"

For example, in this blog post someone is trying to get the type of a column in a database, doing something like this:

object val = reader.GetFieldType(index);
Type runtimeType = val.GetType();
PropertyInfo propInfo = runtimeType.GetProperty("UnderlyingSystemType");
Type type = (Type)propInfo.GetValue(val, null);

Since val is already a Type object, val.GetType() will return another Type object representing the type System.RuntimeTime as this is the concrete type used to represent the original type object. The blog post then shows some unnecessary reflection trickery, to get the type of the original type object, when really all that was required was:

Type type = reader.GetFieldType(index) as Type;

So if your Type object is reporting that it represents a System.RuntimeType, make sure you have not accidentally called GetType() on a type you have already got.

Ergwun
  • 12,579
  • 7
  • 56
  • 83
  • The first code snippet only checks if the object is an instance of `Type`—it'll return true even if you pass `typeof(int)`. The second code snippet doesn't work for comparing `typeof(string).GetType()` and `typeof(Type)`. – Mark Cidade Apr 21 '11 at 00:25
  • This is exactly what I was looking for! I did find Thomas Danecker's post but not Doogal Bell's – Edgar Gonzalez Apr 21 '11 at 00:28
  • 1
    @Mark Cidade. Well spotted, thanks. Have fixed answer to be more helpful, hopefully clearing up any confusion I introduced by citing that blog post. – Ergwun Apr 21 '11 at 02:54
  • @Edgar Gonzalez: That blog post I referenced was actually rather misleading. Please see my updated answer for better info. – Ergwun Apr 21 '11 at 02:58
4

From the answer to Different between System.Type and System.RuntimeType by Thomas Danecker:

System.Type is an abstract base class. The CLR has it's concrete implementation in the internal type System.RuntimeType. Because of this typeof(string).GetType() returns a RuntimeType but typeof(Type) returns a normal Type. Using the .Equals method does in fact an object.ReferenceEquals which returns false. To get the expecting results, you may use type.IsInstanceOfType(element). This will also return true if element is of a derived type. If you'd want to check for the exact type, the return-value of false of your method is desired result. You may also use checkType(arrayType, Type.GetType("System.RuntimeType")) to check for the RuntimeType.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • 2
    "does in fact an" - Can we get a grammar correction. This is like the crux of the whole thing and it doesn't make sense. – N73k Jul 10 '19 at 18:26
3

In brief...

    "".GetType().ToString()           == "System.String"

    "".GetType().GetType().ToString() == "System.RuntimeType"

The way I now think about it is that System.Type is a base type for the type that represents object type request results at runtime, namely System.RuntimeType. So, when you request the type of an object, as in, "".GetType(), the instance of System.Type returned is it's descendent, System.RuntimeType. In fact, one should expect that the typeof(System.Type).GetType() should be System.RuntimeType as well, but I think the framework specifically prevents this...symmetry.

George
  • 2,451
  • 27
  • 37