Pourquoi est-il impossible d'appeler des méthodes statiques sur Nullable abréviations?
j'ai pensé T?
est juste un raccourci de compilateur pour Nullable<T>
. Selon MSDN:
La syntaxe
T?
est un raccourci pourNullable<T>
, oùT
est un type valeur. Les deux formes sont interchangeables.
cependant, il y a une petite différence (insignifiante): Visual Studio ne me permet pas d'appeler des méthodes statiques sur des raccourcis:
bool b1 = Nullable<int>.Equals(1, 2); //no error
bool b2 = int?.Equals(1, 2); //syntax error "Invalid expression term 'int'"
Pourquoi? Y a-t-il une raison à cette limitation?
2 réponses
Votre MSDN devis échos §4.1.10 de C# 5.0 spécifications:
un type nul est écrit
T?
, oùT
est le type sous-jacent. Cette syntaxe est abrégée pourSystem.Nullable<T>
, et les deux formes peuvent être utilisés de façon interchangeable.
mais "interchangeables" est une simplification excessive. Il est vrai que T?
signifie System.Nullable<T>
, mais comme vous l'avez découvert, vous ne pouvez pas utiliser T?
partout que vous pouvez utiliser System.Nullable<T>
. En particulier, le genre de membre d'accès (§7.6.4) dans votre exemple, nécessite un simple-nom (§7.6.2):
[§7.6] les expressions primaires comprennent les formes les plus simples des expressions.
expression primaire:
primaire-pas-tableau-création-expression
array-création-expressionprimaire-pas-tableau-création-expression
littérale
simple-nom
mise entre parenthèses de l'expression
membre d'accès
...[§7.6.2]simple-nom est soit de la forme
I
, ou de la formeI<A1, ..., AK>
, oùI
est un identifiant unique et<A1, ..., AK>
est facultatif type de l'argument de la liste.[§7.6.4]membre d'accès est soit de la forme
E.I
, ou de la formeE.I<A1, ..., AK>
, oùE
est un expression primaire,I
est un identifiant unique et<A1, ..., AK>
facultatif type de l'argument de la liste.
Nullable<T>
est un simple-nom et T?
n'est pas le cas, l'ancien compile tandis que le second ne l'est pas.
pourquoi le C# les concepteurs de langues ont besoin d'un membre d'accès expression simple-nom plutôt tapez? Je suppose qu'ils sont les seuls à pouvoir le dire avec certitude, mais peut-être que cette exigence simplifiait la grammaire: dans une expression, le compilateur peut supposer que ?
est toujours l'opérateur conditionnel (ternaire) au lieu d'un spécificateur de type éventuellement nul.
en rétrospective, cependant, ce fut un choix heureux qui a permis à C# 6.0 d'ajouter le ?.
opérateur Sans peut-être casser les programmes existants. Par exemple, considérons cet exemple pathologique:
struct S
{
public bool Equals(int x, int y) { return false; }
}
class C
{
public static void Main()
{
S? S = new S();
Console.WriteLine(S?.Equals(1, 1)); // "True" or "False"?
}
}
Devrait S?.Equals
être analysée comme Nullable<S> . Equals
, un appel à Equals
méthode statique de la classe Object
? Ou doit-elle être analysée comme S ?. Equals
, un appel null-conditionnel à Equals
méthode de l'instance de la variable S
? Parce que S?
n'est pas simple-nom, c'est sans ambiguïté le dernier.
alors que vous avez raison sur la syntaxe, la méthode Equals peut être appelée à partir du type par défaut en utilisant le type Nullable comme paramètre.
Vous pouvez essayer ce test avec la valeur que vous voulez :
int? i = 4;
int? j = null;
Assert.AreEqual(Nullable<int>.Equals(i, j), int.Equals(i, j));