En IL à ce niveau, null
est juste null
. Le compilateur savait que c'était null
car c'est ce que vous avez écrit. Le compilateur n'a donc pas besoin d'appeler l'opérateur de cast. Casting null
à un objet donnera juste null
.
Il s'agit donc d'une "optimisation" ou d'une simplification au moment de la compilation, si vous voulez.
Puisque c'est légal, pour lancer null
à un autre type d'objet, il n'y a ni avertissement ni erreur signalée à ce sujet.
Notez qu'apparemment, le compilateur ne le fera pas, même s'il est capable de vérifier que la valeur à convertir est effectivement garantie comme étant null
si elle n'est pas littérale.
Votre exemple :
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
(J'ai ajouté l'appel à GC.KeepAlive
pour éviter que le compilateur n'abandonne la variable entière parce qu'elle n'est utilisée nulle part).
Si je bourre le null
en un objet d'abord, sans possibilité de le modifier :
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