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ùTest 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ùTest 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ùIest 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ùEest un expression primaire,Iest 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));