2016-03-20 7 views
0

Ich habe 2 Listen, zuerst auf Eltern Objekte zweite Kind Objekte. Das untergeordnete Objekt hat eine zusätzliche Eigenschaft, die ich mit einer Eigenschaft der übergeordneten Klasse vergleichen möchte.Liste des Kindes mit der Liste der Eltern durch einen bestimmten Wert vergleichen

hier ist das Beispiel

public class Parent 
{ 
    public int X { get; set; } 
} 

public class Child : Parent 
{ 
    public int Y { get; set; } 
} 

public class ClassXCompare : IEqualityComparer<Parent> 
{ 
    public bool Equals(Parent x, Parent y) 
    { 
     var child = (Child)y; 
     return x.X == child.Y; 
    } 

    public int GetHashCode(Parent parent) 
    { 
     int parentXhash = parent.X.GetHashCode(); 
     // Calculate the hash code for the product. 
     return parentXhash ; 
    } 
} 

und jetzt, wenn ich die folgende testen, ist es immer

var parentList= new List<Parent> 
     { 
      new Parent {X = 5}, 
      new Parent {X = 6} 
     }; 
     var childList= new List<Child> 
     { 
      new Child {Y = 5}, 
      new Child {Y = 6} 
     }; 
     var compare = new ClassXCompare(); 
     var diff = parentList.Except(childList, compare); 
     Assert.IsTrue(!diff.Any()); // Fail ??? 

nicht glaube, ich meine Frage in der GetHashCode Funktion befindet sich

Beliebig Idee, wie man das löst?

(Bitte ignorieren Sie das Design der Anwendung ist das vereinfachte Version der Ausgabe)

+0

Sind Sie sicher, dass 'y' immer ein' Child' in 'var child = (Child) y;' ist? Und in jedem Fall, bitte, klären Sie, was genau Sie meinen, "es scheitert immer" (Ausnahme, falsches Ergebnis ...). –

+0

Ja y ist immer ein Kind, es gibt keine Ausnahmen, ** var diff = parentList.Except (childList, vergleichen); ** sollte leer zurückkehren, aber es ist nicht – Maro

Antwort

2

Das ist wirklich schreckliches Design. Die Notwendigkeit, im Vergleich auf bestimmte Typen umzustellen, wird Ihnen kein Ende bereiten.

Der folgende Code wird jedoch übergeben. Beachten Sie die unterschiedliche Methode des Castings, die Null-Überprüfung und die Reihenfolge der Listen in der Ausnahmezeile.

Das Problem bestand darin, dass die Child-Instanzen X nicht festlegen und die Reihenfolge, in der die Except-Methode Werte in Equals übergibt, bedeutete, dass "x" das Child nicht "y" war.

Dies kann "funktionieren", aber Sie sollten Ihr Design ernsthaft überdenken.

public class Parent 
{ 
    public int X { get; set; } 
} 

public class Child : Parent 
{ 
    public int Y { get; set; } 
} 

public class ClassXCompare : IEqualityComparer<Parent> 
{ 
    public bool Equals(Parent x, Parent y) 
    { 
     var child = y as Child; 

     return child != null && x.X == child.Y; 
    } 

    public int GetHashCode(Parent parent) 
    { 
     var c = parent as Child; 
     if (c == null) 
      return parent.X.GetHashCode(); 
     else 
      return c.Y.GetHashCode(); 
    } 
} 

[TestClass] 
public class UnitTest1 
{ 
    [TestMethod] 
    public void TestMethod1() 
    { 
     var parentList = new List<Parent> 
      { 
        new Parent {X = 5}, 
        new Parent {X = 6} 
      }; 
     var childList = new List<Child> 
      { 
        new Child {Y = 5}, 
        new Child {Y = 6} 
      }; 
     var compare = new ClassXCompare(); 
     var diff = childList.Except(parentList, compare); 
     Assert.IsTrue(!diff.Any()); // Fail ???  
    } 
} 
+0

danke, ich stimme über das Design, weshalb ich in meiner Frage bemerkt, die Sache ist, ich habe keine Befugnis, das Design zu ändern.deshalb muss ich das umsetzen :-(danke nochmal ich werde test – Maro

+0

fair genug machen, ist das nicht immer so :) – AndyPook

+0

Danke Andy, ich habe deine Antwort markiert, ich werde diese Frage erneut stellen, weil ich in ähnlicher Situation bin vergleiche 2 doubles aber ich bekomme immer falsch, aber das ist eine andere Frage – Maro

0

Equals in Set/Dictionary wird nur nur aufgerufen werden, wenn GetHashCode den gleichen Wert für beide Positionen gibt - siehe General advice and guidelines on how to properly override object.GetHashCode(). Der einfachste Weg, um es zu beheben ist, so etwas zu verwenden, in denen Kinder Wert verwendet wird HashCode wenn verfügbar zu berechnen:

public class ClassXCompare : IEqualityComparer<Parent> 
{ 
    public bool Equals(Parent x, Parent y) 
    { 
     var child = (Child)y; 
     return x.X == child.Y; 
    } 

    public int GetHashCode(Parent parent) 
    { 
     var child = parent as Child; 
     return child == null ? 
      parent.X : child.Y. 
    } 
} 

Obwohl es nicht sehr erweiterbar ist, wenn Sie mehr untergeordneten Klassen behandeln müssen.

Nicht sicher, dass es eine einfache Möglichkeit gibt, mehrere untergeordnete Klassen zu behandeln, außer mit einigen benutzerdefinierten generic IEqualityComparer und sogar das wird es nur ein wenig verkürzen.

P.S. Auch ich bin mir nicht sicher, dass der zweite Parameter immer ein Child sein wird (bezweifle, dass der Standard es abdeckt, obwohl die aktuelle Implementierung in dieser bestimmten Verwendung in einer angemessenen Weise zu funktionieren scheint), so müssen Sie möglicherweise die IEqualityComparer nachsichtiger machen Reihenfolge der Parameter.

Verwandte Themen