The ECMA Common Language Infrastructure documentation says this about the CIL "isinst class" instruction:
Correct CIL ensures that class is a valid typeref or typedef or typespec token indicating a class, and that obj is always either null or an object reference.
This implies that a valuetype is not allowed, right? But mscorlib.dll contains a method System.RuntimeTypeHandle::Equals(object obj) with the following instruction:
IL_0001: isinst System.RuntimeTypeHandle
And System.RuntimeTypeHandle is a valuetype. Can anybody put me right here?
Have a look at the declaration of RuntimeTypeHandle
:
.class public sequential ansi serializable sealed beforefieldinit RuntimeTypeHandle
extends System.ValueType
implements System.Runtime.Serialization.ISerializable
Although RuntimeTypeHandle
is declared as a struct its representation in CIL is some kind of special class. In other words, you can imagine structs as special classes that inherit from System.ValueType
and whose attributes follow a strict order.
With that in mind isinst
would be callable with RuntimeTypeHandle
. For what I interpret isinst
is not limited to reference types at all as long as there is a class representing the type.
Let's say we write in C#:
var i = 4;
var b = i is Int32;
We get a compiler warning
Warning: The given expression is always of the provided ('int') type.
What happens? We assign 4
to i
. i
becoms an int
. On the next line i
is being auto-boxed to its corresponding ReferenceType
(class), so that the warning is obvious. We could even write
var b = i is int;
I hope this can contribute to some kind of clearification on this topic.