2017-05-31 3 views
24

Ich dachte T? für Nullable<T> nur ein Compiler eine Abkürzung ist. Nach MSDN:Warum ist es nicht möglich, statische Methoden auf Nullable <T> Kürzel zu nennen?

Die Syntax T? ist eine Abkürzung für Nullable<T>, wo T Wert Typ ist. Die beiden Formen sind austauschbar.

Allerdings gibt es ein wenig (unbedeutend) Unterschied: Visual Studio erlaubt mir nicht, statische Methoden auf Kürzeln zu nennen:

bool b1 = Nullable<int>.Equals(1, 2); //no error 
bool b2 = int?.Equals(1, 2); //syntax error "Invalid expression term 'int'" 

Warum? Gibt es einen Grund für diese Einschränkung?

+1

Es ist eine Syntax-Sache. Der Parser kann das "?." Nicht herausfinden. – jwg

+2

Das ist eine gute Frage, obwohl ich nicht weiß, was das bedeuten würde, Was würden wir versuchen, mit Nullable .Equals (1, 2) zu testen? (Ich bin nicht gemein, ist eine echte Frage) – hardkoded

+2

Beginnend mit C# 6, '?.' Als Null-bedingte Prüfung verwendet, daher ist es Syntaxfehler. Bei Verwendung einer früheren Version, bei der "?." Nicht als einzelner Operator erkannt wird, ist die Situation möglicherweise anders. –

Antwort

12

Ihre MSDN Zitat Echos §4.1.10 der C# 5.0-Spezifikation:

Ein Nullable Type T? geschrieben wird, Dabei ist T der zugrunde liegende Typ. Diese Syntax wird für System.Nullable<T> Kurzschrift, und die beiden Formen können austauschbar verwendet werden.

Aber "austauschbar" ist eine übermäßige Vereinfachung. Es stimmt, dass T? bedeutet System.Nullable<T>, aber wie Sie entdeckt haben, können Sie T? nicht überall verwenden, dass Sie System.Nullable<T> verwenden können. Insbesondere die Art von Mitglied-Zugang (§7.6.4) in Ihrem Beispiel erfordert einen einfach Namen (§7.6.2): ​​

[§7.6] Primäre Ausdrücke, die einfachstenen Formen schließen von Ausdrücken.

primär expression:
Primär-no-Array-Erstellungs Ausdruck
Array-creation-expression

Primär-no-Array-Erstellungs Ausdruck
wörtliche
einfach Name
klammerten-expression
Mitglied-Zugang
...

[§7.6.2] Ein einfacher -name entweder die Form oder die I Form I<A1, ..., AK>, wo I ist ein einzelner Identifikator und <A1, ..., AK> ist eine optionale Typargumentliste.

[§7.6.4] A Mitglied-access entweder die Form oder die E.I Form E.I<A1, ..., AK>, wo E ist ein Primärausdruck, I eine einzige Kennung und <A1, ..., AK> ist ein optionaler Typ -argument-list.

Nullable<T> ist ein einfach Name und T? ist nicht, so die ehemalige compiles während letztere nicht.

Warum benötigen die Sprache C# Designer einen Memberzugriff Ausdruck einen einfach Namen zu verwenden, wie einen Typen dagegen? Ich nehme an, nur sie können es mit Sicherheit sagen, aber vielleicht hat diese Anforderung die Grammatik vereinfacht: In einem Ausdruck kann der Compiler annehmen, dass ? immer der bedingte (ternäre) Operator ist und möglicherweise kein NULL-fähiger Typspezifizierer.

Im Nachhinein war dies jedoch eine glückliche Wahl, die es C# 6.0 erlaubte, den Operator ?. hinzuzufügen, ohne bestehende Programme zu unterbrechen. Betrachten wir zum Beispiel diesen pathologischen Beispiel:

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"? 
    } 
} 

Sollte S?.Equals als Nullable<S> . Equals, einen Aufruf der Equals statische Methode der Klasse Object analysiert werden? Oder sollte es als S ?. Equals, ein Null-bedingter Aufruf an die Equals Instanz Methode der Variablen S geparst werden? Weil S? kein einfacher Name ist, ist es eindeutig Letzteres.

0

Während Sie rechts über die Syntax sind, dann kann die Equals-Methode vom Typ Nullable-Typ als Parameter mit Standard aufgerufen werden.

können Sie dieses Gerät zu testen versuchen mit dem, was von Ihnen gewünschten Wert:

int? i = 4; 
int? j = null; 
Assert.AreEqual(Nullable<int>.Equals(i, j), int.Equals(i, j)); 
+0

Das liegt daran, dass beide Methodenaufrufe nur zu "object.Equals" aufrufen, was zwei "object" -Instanzen erfordert. Diese sind beide identisch mit "object.Equals". – Servy

+0

Sie haben Recht. Ich habe nur darauf hingewiesen, dass es nicht nötig ist, "int? .Equals()" zu nennen. – Aboc

Verwandte Themen