2013-05-04 2 views
14

Dies ist kein besonderes Problem zu lösen. Einfach eine Compilerfrage.Warum null == false führt nicht zum Kompilierungsfehler in C#?

Warum führt der folgende Code nicht zum Kompilierungsfehler? Es wird ein Referenztyp mit einem primitiven Typ verglichen. Sowohl Null als auch Falsch müssen in etwas interpretiert werden, damit der Compiler einen Vergleich durchführen kann. Oder sucht der Parser einfach nach einem solchen Muster und ersetzt es durch false?

if(null == false) { } 
+4

Werttyp oder nicht, 'false' ist immer noch ein Objekt. Es wird wahrscheinlich für den Vergleich eingerahmt werden. – cHao

+6

@cHao: Ihre Vermutung ist falsch. Der Gleichheitsoperator wurde speziell entwickelt, um Boxen zu vermeiden. Lesen Sie die Spezifikation für Details. –

Antwort

28

Es ist legal, weil der gehobene Vergleichsoperator verwendet wird. Wenn Sie eine bool mit einer null vergleichen, werden sowohl bool als auch null implizit in Nullable<bool> konvertiert und der Vergleichsoperator für Nullable<bool> wird verwendet. Sie erhalten eine Warnung, weil es offensichtlich immer falsch ist.

+4

Ich mag Ihre Antwort besser, da es erklärt, warum es erlaubt ist und wie es funktioniert. Anstatt nur das Offensichtliche zu sagen. Der Compiler (im Debug-Modus mit deaktivierten Optimierungen) versucht übrigens nicht einmal, ihn zu emittieren. Es gibt einfach "falsch" in den Code aus. – Virtlink

+0

Dies ist in Abschnitt 7.9.10 der Spezifikation (Gleichheitsoperatoren und Null) falsch. Diese Erklärung gilt nur für den Fall, dass für "null == x", "x" ein Nullwerttyp ist. Die Spezifikation besagt, dass dies äquivalent zu "x.HasValue" ist. Da das Literal 'false' kein NULL-fähiger Typ ist, hängt der Grund dafür nicht mit dem aufgehobenen Vergleichsoperator zusammen. – drf

+4

'false' ist möglicherweise kein NULL-fähiger Typ, aber vom Typ' bool' und es gibt eine implizite Konvertierung zwischen 'bool' und' bool? ' –

12

Abschnitt 7.10.6 der Sprachspezifikation (Referenz Typ Gleichheitsoperator) heißt es:

Das x == null Konstrukt selbst erlaubt ist, wenn T einen Werttyp darstellen könnte, und das Ergebnis ist definiert einfach falsch zu sein, wenn T ist ein Werttyp.

Diese Bestimmung setzt voraus, dass null == falsefalse sein, und kein Compiler-Fehler.

+2

Dieser Abschnitt der Spezifikation gilt nur für Typparameter. –

15

Tejas Antwort ist korrekt. Um genauer auf einige Ihrer Punkte einzugehen:

Warum führt der folgende Code nicht zum Kompilierungsfehler?

Die Frage ist nicht zu beantworten; es erzeugt keinen Fehler, weil es ein gesetzlicher Code ist, aber das ist eine Tautologie.

Wenn Ihre Frage tatsächlich lautet: "Welcher Abschnitt der C# Spezifikation macht dies legal?", Dann ist das eine beantwortbare Frage. Der Abschnitt über aufgehobene Gleichstellungsoperatoren macht es legal.

Es wird ein Referenztyp mit einem primitiven Typ verglichen.

Es ist nicht. Vermeiden Sie zunächst den Begriff "primitiver Typ"; Die Spezifikation definiert es nicht klar und es ist kein nützliches Konzept in C#. Sie wollten sagen, ich denke, dass es einen Wert des Referenztyps mit einem Wert des Werttyps vergleicht.

Zweitens ist das auch nicht korrekt. Das Null-Literal ist nicht vom Referenztyp oder Werttyp; es ist nicht von Art. Es ist umwandelbar zu jedem Nullwerttyp oder jedem Referenztyp, aber es ist von keinem Typ nur für sich.

In diesem Fall wird das Null-Literal in den Nullwert-Bool-Typ konvertiert.

Sowohl Null als auch False müssen in etwas interpretiert werden, damit der Compiler einen Vergleich durchführen kann.

Korrekt. Sie werden als nullbare Boole interpretiert.

sucht der Parser einfach nach einem solchen Muster und ersetzt es durch false?

Nein, aber das ist eine ausgezeichnete Schätzung. Der Compiler würde Constant-Falte sagen true == false bis zu false, aber es führt keine Faltungsoptimierungen durch, die NULL-Werttypen enthalten. Die Sprache könnte neu entworfen werden, um eine konstante Faltung bei Operationen mit Nullwert-Operanden zu unterstützen; hatte Nullwertwerte kontrafaktisch in Version eins, das vorgeschlagene Feature wäre wahrscheinlich unterstützt worden.

+0

Danke für die Einstellung der Datensätze gerade. – weilin8

+0

War der Vergleich auch in C# vor Nullable-Typen gültig? –

+0

@AndersForsgren: War * was * Vergleich gültig, in welcher Version von C#? –

Verwandte Themen