2008-09-16 3 views

Antwort

117

Verwendung ReferenceEquals:

Foo foo1 = null; 
Foo foo2 = new Foo(); 
Assert.IsFalse(foo1 == foo2); 

public static bool operator ==(Foo foo1, Foo foo2) { 
    if (object.ReferenceEquals(null, foo1)) 
     return object.ReferenceEquals(null, foo2); 
    return foo1.Equals(foo2); 
} 
17

Guss im Überlast Methode zum Objekt:

public static bool operator ==(Foo foo1, Foo foo2) { 
    if ((object) foo1 == null) return (object) foo2 == null; 
    return foo1.Equals(foo2); 
} 
+1

Genau. Sowohl '(object) foo1 == null' oder' foo1 == (object) null' gehen auf die eingebaute Überladung '== (object, object)' und nicht auf die benutzerdefinierte Überladung '== (Foo , Foo) '. Es ist wie Überladungsauflösung bei Methoden. –

+2

Zu zukünftigen Besuchern - die akzeptierte Antwort ist eine Funktion, die das == des Objekts ausführt. Das ist im Grunde das Gleiche wie die akzeptierte Antwort, mit einem Nachteil: Es braucht eine Besetzung. Die Antwort ist also überlegen. – Mafii

+0

@Mafii Die Besetzung ist * rein * eine Kompilierzeitoperation. Da der Compiler weiß, dass die Umwandlung nicht fehlschlagen kann, muss zur Laufzeit nichts überprüft werden. Die Unterschiede zwischen den Methoden sind völlig ästhetisch. – Servy

4

Wie dem auch sei Object.ReferenceEquals(foo1, null)

Versuchen Sie, würde ich nicht empfehlen, den == Betreiber Überlastung; Es sollte verwendet werden, um Referenzen zu vergleichen, und Equals für "semantische" Vergleiche verwenden.

8

Verwenden Sie ReferenceEquals. Von der MSDN forums:

public static bool operator ==(Foo foo1, Foo foo2) { 
    if (ReferenceEquals(foo1, null)) return ReferenceEquals(foo2, null); 
    if (ReferenceEquals(foo2, null)) return false; 
    return foo1.field1 == foo2.field2; 
} 
-4

können Sie versuchen, eine Objekteigenschaft zu verwenden und die resultierende Nullreferenceexception zu fangen. Wenn die Eigenschaft, die Sie versuchen, geerbt oder von Object überschrieben wird, funktioniert dies für jede Klasse.

public static bool operator ==(Foo foo1, Foo foo2) 
{ 
    // check if the left parameter is null 
    bool LeftNull = false; 
    try { Type temp = a_left.GetType(); } 
    catch { LeftNull = true; } 

    // check if the right parameter is null 
    bool RightNull = false; 
    try { Type temp = a_right.GetType(); } 
    catch { RightNull = true; } 

    // null checking results 
    if (LeftNull && RightNull) return true; 
    else if (LeftNull || RightNull) return false; 
    else return foo1.field1 == foo2.field2; 
} 
+0

Wenn Sie viele Nullobjekte haben, kann die Ausnahmebehandlung einen großen Aufwand bedeuten. – Kasprzol

+2

Haha, ich stimme zu, dass dies nicht die beste Methode ist. Nach der Veröffentlichung dieser Methode habe ich sofort mein aktuelles Projekt überarbeitet, um stattdessen ReferenceEquals zu verwenden. Obwohl es suboptimal ist, funktioniert es und ist daher eine gültige Antwort auf die Frage. –

4

Wenn ich bool Equals(object obj) haben overrided und ich möchte den Bediener == und Foo.Equals(object obj) die gleiche Antwort zurück, ich implementieren in der Regel die != Operator wie folgt aus:

public static bool operator ==(Foo foo1, Foo foo2) { 
    return object.Equals(foo1, foo2); 
} 
public static bool operator !=(Foo foo1, Foo foo2) { 
    return !object.Equals(foo1, foo2); 
} 

Der Betreiber == wird dann schließlich tun Die Null-Prüfungen für mich am Ende rufen foo1.Equals(foo2), die ich übersteuert habe, um die tatsächliche Prüfung zu tun, wenn die beiden gleich sind.

+0

Das fühlt sich sehr passend an; Betrachten wir die Implementierung von ['Object.Equals (Object, Object)'] (http://referencesource.microsoft.com/mscorlib/system/object.cs.html#f2a579c50b414717) Seite an Seite mit ['Object.ReferenceEquals (Object, Object) '] (http://referencesource.microsoft.com/mscorlib/system/object.cs.html#4d607d6d56a93c7e), es ist ziemlich klar, dass' Object.Equals (Object, Object) 'alles tut, was in der andere Antworten aus der Box. Warum nicht benutzen? – tne

+0

@tne Da es keinen Sinn macht, den Operator '== zu überladen, wenn alles, was Sie wollen, das Standardverhalten ist.Sie sollten nur dann überladen, wenn Sie eine benutzerdefinierte Vergleichslogik implementieren müssen, d. H. Etwas mehr als eine Referenzgleichheitsprüfung. – Dan

+0

@Dan Ich bin zuversichtlich, dass Sie meine Bemerkung missverstanden haben; in einem Kontext, in dem es bereits feststeht, dass das Überladen von '=' wünschenswert ist (die Frage impliziert es), unterstütze ich einfach diese Antwort, indem ich vorschlage, dass 'Object.Equals (Object, Object)' andere Tricks wie 'ReferenceEquals' macht oder explizite Umsetzungen unnötig (also "warum nicht benutzen?", "es" ist "Equals (Object, Object)"). Auch wenn nicht verwandt, ist Ihr Punkt auch korrekt, und ich würde weiter gehen: Überladen Sie nur '==' für Objekte, die wir als "Wertobjekte" klassifizieren können. – tne

1

Mein Ansatz ist

(object)item == null 

, auf dem auf object den eigenen Gleichheitsoperator ich verlasse mich zu tun, was nicht schief gehen kann. Oder eine benutzerdefinierte Erweiterungsmethode (und eine Überlast):

public static bool IsNull<T>(this T obj) where T : class 
{ 
    return (object)obj == null; 
} 

public static bool IsNull<T>(this T? obj) where T : struct 
{ 
    return !obj.HasValue; 
} 

oder mehr Fälle zu handhaben, können sein:

public static bool IsNull<T>(this T obj) where T : class 
{ 
    return (object)obj == null || obj == DBNull.Value; 
} 

Die Einschränkung verhindert IsNull auf Werttypen. Nun ist es so süß wie

object obj = new object(); 
Guid? guid = null; 
bool b = obj.IsNull(); // false 
b = guid.IsNull(); // true 
2.IsNull(); // error 

Aufruf was bedeutet, ich habe eine konsistente/nicht-fehleranfällige Stil der Überprüfung auf NULL-Werte im gesamten Gebäude. Ich habe auch (object)item == null is very very very slightly faster than Object.ReferenceEquals(item, null) gefunden, aber nur wenn es wichtig ist (ich arbeite gerade an etwas, wo ich alles optimieren muss!).

Um eine vollständige Anleitung zur Umsetzung der Gleichstellung Kontrollen zu sehen, What is "Best Practice" For Comparing Two Instances of a Reference Type?

+0

Nitpick: Leser sollten ihre Abhängigkeiten beobachten, bevor sie auf Features wie den Vergleich von 'DbNull' springen, IMO die Fälle, in denen * * keine Probleme im Zusammenhang mit [SRP] erzeugen würde (https://en.wikipedia.org/wiki/Single_responsibility_principle) sind ziemlich selten. * Aber nur den Code Geruch, könnte es sehr gut geeignet sein. * – tne

-3

Ein häufiger Fehler bei Überlastungen des Betreibers sieht == ist (a == b), verwenden (a ==null) oder (b == null) Referenz Gleichheit zu überprüfen.Dies führt stattdessen zu einen Aufruf an den überladenen Operator ==, was eine infinite loop verursacht. Verwenden Sie ReferenceEquals oder den Typ auf Objekt, um die Schleife zu vermeiden.

Check out diese

// If both are null, or both are same instance, return true. 
if (System.Object.ReferenceEquals(a, b))// using ReferenceEquals 
{ 
    return true; 
} 

// If one is null, but not both, return false. 
if (((object)a == null) || ((object)b == null))// using casting the type to Object 
{ 
    return false; 
} 

Referenz Guidelines for Overloading Equals() and Operator ==

+1

Es gibt bereits mehrere Antworten mit all diesen Informationen. Wir brauchen keine siebte Kopie derselben Antwort. – Servy

1

Wenn Sie C# 7 oder höher verwenden können Sie null konstante Musterabgleich verwenden:

public static bool operator==(Foo foo1, Foo foo2) 
{ 
    if (foo1 is null) 
     return foo2 is null; 
    return foo1.Equals(foo2); 
} 

Dies gibt Ihnen etwas sauberere Code als das aufrufende Objekt. ReferenceEquals (foo1, null)

+0

oder 'öffentlicher statischer Booloperator == (Foo foo1, Foo foo2) => foo1? .Equals (foo2) ?? foo2 ist null; ' –

0

The static Equals(Object, Object) method zeigt an, ob zwei Objekte, objA und objB, gleich sind. Sie können auch Objekte testen, deren Wert null für die Gleichheit ist. Er vergleicht objA und objB für die Gleichstellung wie folgt:

  • Es bestimmt, ob die beiden Objekte die gleiche Objektreferenz darstellen. Wenn dies der Fall ist, gibt die Methode true zurück. Dieser Test entspricht dem Aufruf der Methode ReferenceEquals. Wenn sowohl objA als auch objBnull sind, gibt die Methode true zurück.
  • Es bestimmt, ob entweder objA oder objBnull ist. Wenn ja, gibt es false zurück. Wenn die beiden Objekte nicht die gleiche Objektreferenz darstellen und auch nicht null, ruft sie objA.Equals(objB) auf und gibt das Ergebnis zurück. Das heißt, wenn objA die Methode Object.Equals(Object) überschreibt, wird diese Überschreibung aufgerufen.

.

public static bool operator ==(Foo objA, Foo objB) { 
    return Object.Equals(objA, objB); 
} 
Verwandte Themen