37 votes

Pourquoi le compilateur me permet-il de convertir un null en un type spécifique en C# ?

Considérez ce code :

var str = (string)null;

Lorsque j'écris le code, c'est mon IL code :

IL_0001:  ldnull

Et IL a tout opérateur Cast mais :

var test = (string) new Object();

El IL Le code est :

IL_0008:  castclass  [mscorlib]System.String

So Casting null a string a été ignorée.

Pourquoi le compilateur me laisse-t-il couler un null à un type spécifique ?

47voto

Lasse V. Karlsen Points 148037

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

19voto

Njol Points 1864

En Java, il y a au moins un cas où il est nécessaire d'intégrer un fichier de type null à un certain type, et ce, en utilisant des méthodes surchargées pour indiquer au compilateur quelle méthode vous voulez exécuter (je suppose que c'est également le cas en C#). Puisqu'un null es 0 (ou tout autre pointeur null représente) quel que soit le type, vous ne verrez aucune différence dans le code compilé (à part la méthode appelée).

13voto

Anton Tykhyy Points 12680

Parce que les spécifications le disent. Voir les §6.1.5, §6.2 et §7.7.6 de la C# 5 standard . Pour ne citer que les parties pertinentes :

§7.7.6 Expressions coulées

A expression coulée de la forme (T)ET est un type y E est un Expression unaire , effectue une conversion explicite ,c opnevrefrosrimos,n ap(ne§6 r.ef2xo)pr lmoisfc iattnh ece oxvnpavlleiurcesi itoo fnc o(n§6v.e2r)s ioofn t(h§6e. 2v)a loufe tohfe valeur de , effectue une conversion explicite (§6.2) de la valeur de E de taper T . [... L]e résultat est la valeur produite par la conversion explicite.

§6.2 Conversions explicites

Les conversions suivantes sont classées comme des conversions explicites :

  • Toutes les conversions implicites.

§6.1.5 Conversions de références implicites

Les conversions de références implicites sont :

  • Du littéral nul à tout type de référence .

8voto

ColinE Points 36907

Le casting d'un null est parfaitement valide - il est parfois nécessaire lors du passage d'arguments à des méthodes surchargées afin d'informer le compilateur de la méthode invoquée.

Voir la question connexe suivante :

Transformation de null en objet ?

4voto

Rory Points 13087

Le but de ce casting est de définir str comme un type String, donc il s'agit moins de savoir si vous pouvez convertir un null en Type que de définir le type de la variable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X