2008-09-17 9 views
7

Mögliche Duplizieren:
How do I check for nulls in an '==' operator overload without infinite recursion?beste Art und Weise null zu behandeln, wenn das Schreiben gleich Operator

Als ich den Operator == für Objekte überlastete ich in der Regel so etwas schreiben:

public static bool operator ==(MyObject uq1, MyObject uq2) { 
     if (((object)uq1 == null) || ((object)uq2 == null)) return false; 
     return uq1.Field1 == uq2.Field1 && uq1.Field2 == uq2.Field2; 
    } 

Wenn Sie nicht zum Objekt ablegen, rekursiert die Funktion in sich selbst, aber ich frage mich, ob Es gibt keinen besseren Weg?

+1

Sehen Sie diese Link auch für eine ordnungsgemäße Rundum-Implementierung http://stackoverflow.com/questions/104158/what-is-best-practice-for-comparing-two-instances-of-a-reference-type – nawfal

Antwort

2

Reference (Objekt obj1, Objekt obj2)

+0

Dies scheint nicht zu das Problem überhaupt ansprechen - ReferenceEquals wird Ihnen beispielsweise nicht sagen, ob eins null ist und das andere nicht. –

+0

Warum stimmen die Leute das ab, von meinem Beispiel ist klar, dass ReferenceEquals nicht das ist, was ich suche –

+0

Heh, +4 Stimmen und -4 Stimmen :) – ripper234

-1
if ((object)uq1 == null) 
    return ((object)uq2 == null) 
else if ((object)uq2 == null) 
    return false; 
else 
    //return normal comparison 

Dieser vergleicht sie als gleich, wenn beide null sind.

+1

Dies macht die gleiche Sache, die mein Beispiel nur in verschachtelten Begriffen –

-1

Folgen Sie die DB Behandlung:

null == <anything> is always false 
+0

Dies betrifft nicht die Sorge, x = = y wenn eins null ist, wird die Funktion rekursieren, wie ich gesagt habe –

2

@ neouser99: Das ist die richtige Lösung, aber der Teil, verpaßt wird, ist, dass, wenn der Gleichheitsoperator überschreibt (der Operator ==) Sie auch die Equals-Funktion außer Kraft setzen sollten und lassen Sie den Operator einfach die Funktion aufrufen. Nicht alle .NET-Sprachen unterstützen das Überladen von Operatoren, daher der Grund für das Überschreiben der Equals-Funktion.

+1

Wirklich? Das ist interessant, ich habe es andersherum gemacht –

+0

Wenn Sie es so machen, stellen Sie sicher, dass der Operator == auf Null prüft. null == immer null. –

7

Wie Microsoft sagt

Eine häufige Fehler bei Überlastungen des operator == (a == b) verwendet werden, (a == null) ist, oder (b == null) an Überprüfen Sie für Referenzgleichheit. Dies führt stattdessen zu einem überladenen Operator ==, der eine Endlosschleife verursacht. Verwenden Sie ReferenceEquals, oder wenden Sie den Typ auf Object, um die Schleife zu vermeiden.

Verwenden Sie also ReferenceEquals (a, null) || ReferenceEquals (b, null) ist eine Möglichkeit, aber Casting zum Objekt ist genauso gut (ist eigentlich äquivalent, glaube ich).

Also ja, es scheint, es sollte einen besseren Weg geben, aber die Methode, die Sie verwenden, ist die eine empfohlen.

Wie jedoch bereits erwähnt wurde, SOLLEN Sie auch beim Überschreiben von == unbedingt Gleiches überschreiben. Wenn LINQ-Anbieter in verschiedenen Sprachen geschrieben werden und die Ausdruckauflösung zur Laufzeit ausgeführt wird, wissen Sie, wann Sie etwas falsch machen werden, selbst wenn Sie den gesamten Code selbst besitzen.

+0

Ja, es ist ein häufiges Problem, aber die Lösung besteht darin, die Equals-Funktion zu überschreiben und den Operator dazu zu bringen, den Aufruf Equals zu überladen. ReferenceEquals löst ein anderes Problem und bietet eine völlig andere Art von Gleichheit. –

+2

Ich glaube, Sie haben die ReferenceEquals-Aufrufe oben falsch verstanden. Ich teste einfach auf Gleichheit mit NULL, mit dem Verständnis, eine tatsächliche Gleichheitsprüfung zusätzlich zu machen. NOT referingequals aufrufen, um die Gleichheit der Argumente zu testen. –

-1

Aber warum erstellen Sie keine Objekt-Member-Funktion? Es kann sicherlich nicht auf einer Null-Referenz aufgerufen werden, also sind Sie sicher, dass das erste Argument nicht Null ist.

Tatsächlich verlieren Sie die Symmetrie eines binären Operators, aber immer noch ...

(Anmerkung auf Purfideas' Antwort: Null könnte Null gleich, ob als Sentinel Wert eines Arrays erforderlich)

denken auch an die Semantik Ihrer == Funktion: Sie manchmal wirklich wollen in der Lage sein wählen, ob Sie testen für

  • Identität (Punkte auf demselben Objekt)
  • Wertgleichheit
  • Equivalence (zB 1,000001 entspricht 0,9999999)
+1

Tut mir leid, das beantwortet die Frage wirklich nicht. Die Frage ist, ob es eine bessere Möglichkeit gibt, auf Gleichheit zu testen, als auf Downcasting. –

0

Verwenden Sie einfach Resharper, um Sie zu erstellen Gleich & GetHashCode Methoden. Es erstellt den umfassendsten Code für diesen Zweck.

aktualisiert ich es nicht absichtlich schreiben - ich ziehe Menschen ReSharper die Funktion statt copy-Einfügen, da die Code-Änderungen von Klasse zu Klasse zu verwenden. Wie für die Entwicklung von C# ohne Resharper - ich verstehe nicht, wie du lebst, Mann.

, Auf jeden Fall hier ist der Code für eine einfache Klasse (generiert durch ReSharper 3.0, die ältere Version - ich habe 4.0 bei der Arbeit, ich erinnere mich nicht zur Zeit, wenn sie identische Code erstellt)

public class Foo : IEquatable<Foo> 
{ 
    public static bool operator !=(Foo foo1, Foo foo2) 
    { 
     return !Equals(foo1, foo2); 
    } 

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

    public bool Equals(Foo foo) 
    { 
     if (foo == null) return false; 
     return y == foo.y && x == foo.x; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(this, obj)) return true; 
     return Equals(obj as Foo); 
    } 

    public override int GetHashCode() 
    { 
     return y + 29*x; 
    } 

    private int y; 
    private int x; 
} 
+1

Und du würdest ihn nicht für diejenigen von uns veröffentlichen wollen, die keine $ 400 zu verlieren haben? –

+0

Warum sollte Bill Wagner in diesem Kapitel nicht mit Ihnen übereinstimmen? http://my.safaribooksonline.com/book/programming/csharp/0321245660/csharp-language-elements/ch01lev1sec9 Er plappert etwas über Equals, das symmetrisch ist. –

+1

@Hamish - Ich weiß nicht, Sie müssen genauer als das sein. – ripper234