64 votes

Quel est le type de littéral nul?

Doreille à tous, je me demande quel est le type d' null littérale en C#?

En Java, l' null littérale est de la spéciale de type null:

Il y a également une valeur null type, le type de l'expression null, ce qui n'a pas de nom. Parce que le type null n'a pas de nom, il est impossible de déclarer une variable de type null ou cast vers le type null. La référence nulle est la seule valeur possible d'une expression de type null. La référence null peut toujours être converti en un type de référence.

En C++11, il y a nullptr (la version recommandée de l'ancien copain NULL), qui est de type std::nullptr_t.

J'ai cherché sur MSDN sur le C#, mais la spécification ne semble pas se prononcer à ce sujet.

58voto

J.Kommer Points 4560

Selon l' ECMA spécification du langage C# :

9.4.4.6 Le littéral null:

Le type d'une valeur null littérale est le type null (§11.2.7).

11.2.7 Le type null:

Le littéral null (§9.4.4.6) renvoie la valeur null, ce qui est utilisé pour indiquer une référence ne pointe pas à n'importe quel objet ou un tableau, ou de la absence de valeur. Le type null est une valeur unique, qui est la la valeur null. D'où une expression dont le type est le type null peut évaluer seulement à la valeur nulle. Il n'existe aucun moyen d'écrire explicitement le type null et, par conséquent, aucun moyen de l'utiliser dans un type déclaré. En outre, le type null ne peut jamais être le type inféré pour un type de paramètre (§25.6.4)

Donc, pour répondre à votre question, la valeur null est son propre type - le type null.

Même si c'est bizarre comme ce n'est pas mentionné dans le C# 4.0 langage de spécification ou le C# 3.0 spécification de langage , mais il est mentionné dans la présentation de C# 3.0, l' ECMA spécification du langage C# et le C# 2.0 spécification du langage.

53voto

Eric Lippert Points 300275

Mise à JOUR: Cette question a été l'objet de mon blog en juillet 2013. Merci pour la grande question!


J. Kommer réponse est bonne (et bien sur pour ce qui est de toute évidence beaucoup de spec à creuser!) mais je pensais ajouter un peu de perspective historique.

Lorsque Mads et j'ai été tri de la formulation exacte des diverses parties de la spécification de C# 3.0, nous nous sommes rendu compte que le "null" type était bizarre. C'est un "type" avec une seule valeur. C'est un "type" que la Réflexion ne sait rien. C'est un "type" qui n'ont pas de nom, que GetType ne retourne jamais, que vous ne pouvez pas spécifier le type d'une variable locale ou un champ ou quoi que ce soit. En bref, c'est vraiment un "type" qui est là uniquement pour rendre le système de type "complète", de sorte que chaque moment de la compilation de l'expression a un type.

Sauf que C# déjà eu des expressions qui n'avaient aucun type: méthode des groupes en C# 1.0, les méthodes anonymes en C# 2.0 et les lambdas en C# 3.0 n'ont pas du tout le type. Si toutes ces choses ne peut avoir aucun type, nous avons réalisé que "null" n'ont pas besoin d'un type ou l'autre. Par conséquent, nous avons supprimé les références à l'inutile "de type null" en C# 3.0.

Comme un détail d'implémentation, les implémentations de Microsoft C# 1.0 à 5.0 toutes ont un objet interne pour représenter le "type null". Ils ont aussi des objets pour représenter les non-existant types de lambdas, les méthodes anonymes et de la méthode des groupes. Cette mise en œuvre, le choix a un certain nombre des avantages et des inconvénients. Sur le coté pro, le compilateur peut demander le type d'une expression et d'obtenir une réponse. Sur la con côté, cela signifie que parfois, des bugs dans le type d'analyse qui devraient avoir écrasé le compilateur au lieu de provoquer des changements sémantiques dans les programmes. Mon exemple préféré est qu'il est possible en C# 2.0 pour utiliser l'expression illégale "null ?? null"; à cause d'un bug du compilateur ne parvient pas à le signaler comme étant une utilisation erronée de l' ?? de l'opérateur, et continue d'en déduire que le type de cette expression est "le type null", même si ce n'est pas un null littérale. Qui va ensuite à cause de beaucoup d'autres en aval de bugs comme le type de l'analyseur tente de faire sens de ce type.

Dans Roslyn nous ne sera probablement pas utiliser cette stratégie; au contraire, nous allons tout simplement faire cuire dans le compilateur de mise en œuvre que quelques-unes des expressions non pas de type.

2voto

emrgee Points 86

Malgré l'absence de type d'exécution, null peut être transtypé en un type lors de la compilation, comme le montre cet exemple.

Au moment de l'exécution, vous pouvez trouver que la variable stringAsObject contient un string , pas seulement un object , mais vous ne pouvez trouver aucun type pour les variables nullString et nullStringAsObject .

 public enum Answer { Object, String, Int32, FileInfo };
private Answer GetAnswer(int i) { return Answer.Int32; }
private Answer GetAnswer(string s) { return Answer.String; }
private Answer GetAnswer(object o) { return Answer.Object; }

[TestMethod]
public void MusingAboutNullAtRuntimeVsCompileTime()
{
    string nullString = null;
    object nullStringAsObject = (string)null;
    object stringAsObject = "a string";

    // resolved at runtime
    Expect.Throws(typeof(ArgumentNullException), () => Type.GetTypeHandle(nullString));
    Expect.Throws(typeof(ArgumentNullException), () => Type.GetTypeHandle(nullStringAsObject));
    Assert.AreEqual(typeof(string), Type.GetTypeFromHandle(Type.GetTypeHandle(stringAsObject)));
    Assert.AreEqual(typeof(string), stringAsObject.GetType());

    // resolved at compile time
    Assert.AreEqual(Answer.String, this.GetAnswer(nullString));
    Assert.AreEqual(Answer.Object, this.GetAnswer(nullStringAsObject));
    Assert.AreEqual(Answer.Object, this.GetAnswer(stringAsObject));
    Assert.AreEqual(Answer.Object, this.GetAnswer((object)null));
    Assert.AreEqual(Answer.String, this.GetAnswer((string)null));
    Assert.AreEqual(Answer.String, this.GetAnswer(null));
}

// Uncommenting the following method overload
// makes the last statement in the test case ambiguous to the compiler
// private Answer GetAnswer(FileInfo f) { return Answer.FileInfo; }
 

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