In IL on this level, null
is just null
. The compiler knew it was null
because that is what you wrote, as such the compiler does not need to call the cast operator at all. Casting null
to an object will just yield null
.
So this is a compile-time "optimization" or simplification if you will.
Since this is legal, to cast null
to another object type, there is neither a warning nor an error reported from this.
Note that apparently the compiler will not do this even thought it may be able to verify that the value being cast is indeed guaranteed to be null
, if it isn't a literal.
Your example:
void Main()
{
var s = (string)null;
GC.KeepAlive(s);
}
IL:
IL_0000: ldnull
IL_0001: stloc.0 // s
IL_0002: ldloc.0 // s
IL_0003: call System.GC.KeepAlive
(I added the call to GC.KeepAlive
to avoid the compiler dropping the entire variable due to it not being used anywhere.)
If I stuff the null
into an object first, with no possibility of it changing:
void Main()
{
object o = null;
var s = (string)o;
GC.KeepAlive(s);
}
IL:
IL_0000: ldnull
IL_0001: stloc.0 // o
IL_0002: ldloc.0 // o
IL_0003: castclass System.String
IL_0008: stloc.1 // s
IL_0009: ldloc.1 // s
IL_000A: call System.GC.KeepAlive
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…