2016-04-28 4 views
1

Ich habe eine Struktur IntVector2, die eine X- und Y-Eigenschaft hat. Der Operator + mitList.Contains funktioniert nicht wie erwartet mit benutzerdefinierten Strukturargument

überschrieben
public static IntVector2 operator +(IntVector2 value1, IntVector2 value2) 
{ 
    value1.X += value2.X; 
    value1.Y += value2.Y; 
    return value1; 
} 

Wenn diese in einer Liste mit mit der Methode enthält, wird es nicht den Gesamtwert der Addition prüft, sondern nur die Variable „aktuelle“

if (visited.Contains(current + dir)) 
    continue; 

Was ist eigentlich hier los?

Edit: Hier ist ein Screenshot der Werte der Variablen, und eine Variablendeklaration, die gleich ist, was ich erwarte den Wert der enthält zu überprüfen.

https://dl.dropboxusercontent.com/u/30062610/Brokestuff.png

Edit2: Hier ist der vollständige Code des Verfahrens, ist es der Beginn einer A * Pathfinding Algorithmus, um den End-Vektor aus dem Startvektor zu finden.

Edit 3: Auch mit der Newstuff-Variable, die einen anderen Wert als der Start hat, trifft die Fortsetzung. Ich bin mir nicht sicher, was es tun könnte. My Equals Override prüft nur, ob X und Y beide gleich sind und gibt wahr zurück, wenn dies der Fall ist.

Hier ist die Gesamtheit des IntVector2 Code: http://pastebin.com/ic108SeF

Bearbeiten 4: Ich änderte den Operator + auf:

 public static IntVector2 operator +(IntVector2 value1, IntVector2 value2) 
    { 
     return new IntVector2((value1.X + value2.X), (value1.Y + value2.Y)); 
    } 

Und das Problem immer noch besteht.

+0

Warum ändern Sie 'value1'? –

+0

Haben Sie Ihre Equals-Definition geändert? ((1,1) + (2,2)). Gleich (3,3) ergibt 'wahr' für mich. – Rob

+0

Ich dachte, dass das Ändern des ersten Arguments mit dem Wert der Sekunde funktionieren würde. Sollte ich es ändern, um einen neuen IntVector2 mit der neuen Summe zurückzugeben, anstatt die erste zu ändern? – user3010006

Antwort

1

Sie haben einen Tippfehler in der Equals Methode:

public override bool Equals(object obj) 
{ 
    if (obj is IntVector2) 
    { 
     return Equals((IntVector2)this); // <-- "this" should be "obj" 
    } 
} 

Der fehlerhafte Code vergleicht this zu this, so dass es gibt immer true.

+0

Ich denke, ich habe es jetzt versucht. Vielen Dank! – user3010006

+0

Funktioniert perfekt, guter Fang :) Danke! – user3010006

+0

Gern geschehen! –

-1

Mit Ihrem aktuellen Code kann Contains die Gleichheit für zwei Strukturinstanzen nicht ermitteln. Wenn Sie IntVector2 :: GetHashCode überschreiben, damit identische Werte den gleichen Hashwert zurückgeben, sollte es wie erwartet funktionieren.

+0

'List' verwendet' GetHashCode' nicht. – Rob

+0

Die Liste darf nicht, aber Object.Equals und List :: Contained verwendet Object.Equals, es sei denn, ein alternativer Vergleich wird bereitgestellt. –

+0

Das ist leider falsch. Sie können einen Breakpoint auf "Equals" setzen, wenn Sie nicht überzeugt sind. Der Standard 'Object.Equals' verwendet' Object.ReferenceEquals' – Rob

1

Ok, ich glaube, ich habe dein Problem herausgefunden.

außer Kraft setzen Ihre equals nicht eine Überschreibung ist, haben Sie es in Ihrem Code wie:

public bool Equals(IntVector2 other) { 
     return (X == other.X) && (Y == other.Y); 
    } 

was Sie haben es eine Methode namens Equals hinzugefügt wurde. Sie haben also die Actual equals-Methode, die Sie überschreiben müssen, überladen. Contains ruft Ihre equals-Methode nicht auf, weil sie die ursprüngliche Methode aufruft, die ein Objekt verwendet.

Und wenn Sie die richtige equals-Methode überschreiben, sollten Sie in guter Praxis GetHashCode implementieren und GetHashCode verwenden, um festzustellen, ob die Objekte wirklich gleich sind.

In Ihrem Fall haben Sie kein Problem, GetHashCode nicht zu überschreiben, da Sie Gleichheit auf zwei Ganzzahlen basieren, die in einer anderen Kopie des IntVector2 identisch sind, und Sie können nicht wirklich einen Integer-Hash-Code dafür berechnen X und Y sind beide Ganzzahlen.Wenn Sie hier eine GetHashCode-Implementierung durchgeführt haben, könnten Sie später auf Fehler stoßen, wenn Sie eine große Anzahl davon haben, könnten Sie mit Dupe-Hash-Codes enden, die ungleiche Objekte sind.

Hier ist der aktualisierte Code, den Sie ausprobieren sollten.

public struct IntVector2 
{ 
    public int X { get; set; } 
    public int Y { get; set; } 

    public static IntVector2 operator +(IntVector2 value1, IntVector2 value2) 
    { 
     value1.X += value2.X; 
     value1.Y += value2.Y; 
     return value1; 
    } 

    public override int GetHashCode() 
    { 
     //overrode this to get rid of warning 
     return base.GetHashCode(); 
    } 

    //This equals get's called, notice the override keyword 
    public override bool Equals(object obj) 
    { 
     if (obj is IntVector2) 
     { 
      IntVector2 vObj = (IntVector2)obj; 
      return vObj.X == this.X && vObj.Y == this.Y;   
     } 
     return false; 
    } 

    //This won't get called, it's not part of the framework, this is adding a new overload for equals that .Net won't know about. 
    public bool Equals(IntVector2 other) 
    { 
     return (X == other.X) && (Y == other.Y); 
    } 

    public override string ToString() 
    { 
     return string.Format("{ value1: {0}, value2: {0} }", X, Y); 
    } 
} 
+0

Man, langsam :( –

+0

Ah ich die falsche Pastebin Link abgehend, ich war an dem anderen suchen, aber diese Tippfehler war auch da. –

+0

Dank Ryios. Ich wünschte, ich Sie beide richtig markieren könnte! Auch meine Konten Noob upvote :(Guter Fang auf, dass, obwohl – user3010006

Verwandte Themen