2013-06-18 21 views
11

Warum ist integer == null ein gültiger boolescher Ausdruck in C#, wenn integer (Variable vom Typ int) nicht nullfähig ist? (Ich bin nicht dagegen, in der Tat ich es mag, aber ich wusste nicht, dass es möglich war)Warum ist Integer == null ein gültiger boolescher Ausdruck in C#?

+1

Sie erhalten eine Warnung, etwas in der Art von "Ausdruck ist immer falsch". Warum es * erlaubt * ist, d. H. Es führt nicht zu einem Kompilierzeitfehler ... Ich nehme an, es ist aus demselben Grund erlaubt; 'while (true)' –

+0

Der C# -Compiler wird diese Zeit bei der Kompilierung auf "false" setzen, wenn er im Freigabemodus kompiliert wird (ein 'ldc.i4.0 'landet in IL). – vcsjones

+1

mögliches Duplikat von [C# okay, wenn Werttypen mit null verglichen werden] (http://stackoverflow.com/questions/1972262/c-sharp-okay-with-comparing-value-types-to-null) –

Antwort

19

Obwohl int selbst ist nicht nullable, gibt es eine implizite Konvertierung in int?, die ist nullable.

An diesem Punkt, wenn die Struktur einen Operator == mit dem gleichen Typ auf beiden Seiten deklariert, dann wird das aufgehoben, um mit NULL-Typen zu arbeiten.

So bedeutet dies nicht kompilieren:

public struct Foo {} 

class Test 
{ 
    static void Main() 
    { 
     Foo x = new Foo(); 
     if (x == null) 
     { 
      ... 
     } 
    } 
} 

... aber wenn man Foo einige Betreiber geben, es tut Kompilierung, und ohne eine Warnung:

public struct Foo 
{ 
    public static bool operator ==(Foo x, Foo y) { return true; } 
    public static bool operator !=(Foo x, Foo y) { return false; } 
    public override bool Equals(object x) { return false; } 
    public override int GetHashCode() { return 0; } 
} 

Der Betreiber Aufruf ist nicht in dem kompilierten Code enthalten, da der Compiler kennt, dass das RHS null ist.

So Code der folgenden Form (wo Foo kann durch jede nicht-NULL festlegbare struct ersetzt werden) hat eine der drei Ergebnisse mit dem MS C# 5 Compiler:

  • CS0472 Warnung (zB mit int)
  • CS0019 Error (benutzerdefinierte Typen, die nicht überlasten ==)
  • Saubere Zusammenstellung (benutzerdefinierte Typen, die == überlasten, einschließlich Guid und DateTime)

Es ist mir nicht klar, warum der Compiler einige "bekannte" Typen anders als normale Strukturen behandelt. EDIT: Wie von Eric in Kommentaren bemerkt, ist dies ein bekannter Fehler im C# -Compiler, der hoffentlich in Roslyn behoben wird.

+0

Bah, bessere Antwort als meine ... –

+0

Verdammt, das ist seltsam! Vielleicht sind Strukturen die Ausnahme? –

+0

@ guillegr123: Ich versuche immer noch, es auszuarbeiten ... –

1

Wie Ed erwähnt gibt es eine Warnung, aber die Warnung verweist auf den Grund: int kann int? Auto-gegossen sein, und null ist ein gültiger Wert für eine Variable vom Typ int?.

+1

Skeet schlug mich durch Sekunden. Verdammt, du Skeet! – Shlomo

+0

Du hast das rückwärts gesagt. Sie wollten sagen, dass "int" implizit in "int" umgewandelt werden kann. –

+0

Ack. Danke Eric. Korrigiert. – Shlomo