Frage

Wie funktioniert der == Operator wirklich funktioniert in C #? Wenn es verwendet, um Objekte der Klasse vergleichen A , wird es versuchen, alle A 's Eigenschaften übereinstimmen, oder wird es für Zeiger auf den gleichen Speicherplatz suchen (oder vielleicht etwas anderes)?

Lassen Sie uns ein hypothetisches Beispiel erstellen. Ich schreibe eine Anwendung, die das Twitter-API verwendet, und es hat ein Tweet Klasse, die alle Eigenschaften eines einzelnen Tweet hat: Text, Absender, Datum und Uhrzeit, Quelle usw. Wenn ich will vergleichen Objekte der Klasse Tweet für Gleichwertigkeit, kann ich nur:

Tweet a, b;
if (a == b)
{
//do something...
}

Wird das prüfen Gleichwertigkeit aller Eigenschaften des Tweet Klasse zwischen a und b

Wenn nicht, wäre der richtige Ansatz der == Betreiber überlasten sein, explizit für Gleichwertigkeit überprüfen aller Felder?

UPDATE: Aus den ersten beiden Antworten, bin ich recht in der Annahme:

  • Wenn der == Operator oder Equals Methode ist nicht für eine Klasse überlastet, der == Operator für die Objekt Klasse verwendet wird.
  • Der == Operator für das Objekt Klasse prüft auf Gleichheit in der Speicherstelle.
  • Ich habe den == Betreiber zu überlasten oder die Equals Methode, um diese Aufgabe zu erfüllen.
  • In der Überlastung, ich habe manuell für Gleichwertigkeit in Eigenschaften zu überprüfen, so gibt es keine Möglichkeit, es zu tun halbautomatisch, sagen wir, in einer Schleife , nicht wahr?

UPDATE # 2: hat Yuriy Kommentar, dass es möglich ist, für die Gleichwertigkeit der Eigenschaften im == Betreiber zu tun überprüfen Sie mit Reflexion . Wie kann dies geschehen? Könnten Sie mir einige Beispiel-Code geben? Dank!

War es hilfreich?

Lösung

MSDN hat eine gute Beispiel wie es zu tun:

   public override bool Equals(object o) 
   {
      try 
      {
         return (bool) (this == (DBBool) o);
      }
      catch 
      {
         return false;
      }
   }

Dann überlasten Sie == und =:

// Equality operator. Returns dbNull if either operand is dbNull, 
   // otherwise returns dbTrue or dbFalse:
   public static DBBool operator ==(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value == y.value? dbTrue: dbFalse;
   }

   // Inequality operator. Returns dbNull if either operand is
   // dbNull, otherwise returns dbTrue or dbFalse:
   public static DBBool operator !=(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value != y.value? dbTrue: dbFalse;
   }

Und vergessen Sie nicht die GetHash Methode zu überlasten.

Edit:

Ich schrieb die folgende schnelle Probe für die Reflexion in einem Vergleich. Dies hätte viel umfassender sein, könnte ich einen Blog auf sie versuchen zu tun, wenn die Leute wollen mich:

public class TestEquals
{
    private int _x;
    public TestEquals(int x)
    {
        this._x = x;
    }

    public override bool Equals(object obj)
    {
        TestEquals te = (TestEquals)obj;
        if (te == null) return false;

        foreach (var field in typeof(TestEquals)
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (!field.GetValue(this).Equals(field.GetValue(te)))
                return false;
        }
        return true;
    }
}

Andere Tipps

Für Referenztypen, die Standardimplementierungen sowohl des == Betreibers und die Equals() Methode wird einfach überprüfen, ob beiden Objekte die gleiche Referenz haben, und sind daher die gleiche Instanz.

Wenn Sie den Inhalt von zwei verschiedenen Objekten zu überprüfen sind gleich, dann müssen Sie den Code schreiben es selbst zu tun, eine oder andere Weise. Es wäre möglich, mit Reflexion zu tun (die MbUnit Test-Framework tut etwas in diese Richtung), aber mit einem schweren Leistungseinbuße und eine gute Chance, dass es nicht ganz tun würde, was man ohnehin erwartet, und Sie sollten == oder Equals und GetHashCode von Hand umsetzen.

Der richtige Ansatz ist die Überlastung der Methode equals der Tweet-Klasse neben dem Operator ==, wie beschrieben hier .

  

Wird das Check für Gleichwertigkeit aller Eigenschaften der Tweet Klasse zwischen a und b?

Nein

  

Wenn nicht, wäre der richtige Ansatz den Operator == explizit überlastet sein, um zu prüfen, für die Gleichwertigkeit aller Felder?

Sie können entweder überlasten die == Operator oder Überlastung der Equals Funktion.

Bearbeiten

gab @Yuriy ein gutes Beispiel für compating alle nicht öffentlichen Variablen. Da ich auch ein Beispiel schrieb, hier ist es (meine vergleicht Objekte)

class TwitterItem
{
    private string myValue = "default value";
    public string Value1
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value2
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value3
    {
        get { return myValue; }
        set { myValue = value; }
    }

    public override bool Equals(object obj)
    {
        if (base.Equals(obj)) return true;

        Type type = typeof(TwitterItem);
        PropertyInfo[] properties = type.GetProperties();

        foreach (PropertyInfo property in properties)
        {
            if (false == property.GetValue(this, null).Equals(property.GetValue(obj, null)))
                return false;
        }

        return true;
    }
}

Sie können die Eigenschaften vergleichen Reflexion mit:

var a = new Entity() { Name = "test", ID = "1" };
var b = new Entity() { Name = "test", ID = "1" };
var c = new Entity() { Name = "test", ID = "2" };
System.Diagnostics.Debug.WriteLine(a.Equals(b));//Returns true
System.Diagnostics.Debug.WriteLine(a.Equals(c));//Returns false


public class Entity
{
    public string Name { get; set; }
    public string ID { get; set; }
    public override bool Equals(object obj)
    {
        var t = obj.GetType();
        foreach (var p in t.GetProperties())
        {
            if (t.GetProperty(p.Name).GetValue(obj, null) != t.GetProperty(p.Name).GetValue(this, null))
                return false;
        }
        return true;
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top