2013-02-22 28 views
5

Ich habe eine Liste, die Objekte enthält, aber diese Objets sind nicht in der Liste eindeutig. Ich wrte diesen Code zu machen einzigartig sie in einer anderen Liste:List.Contains funktioniert nicht richtig

foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => !resultSet.Contains(categoryProductsResult))) 
{ 
    resultSet.Add(categoryProductsResult); 
} 

Aber am Ende resultSet ist das gleiche mit categoryProductsResults.

categoryProductsResult der zweiten Reihe:

enter image description here

resultSet ersten Reihe:

enter image description here

Wie Sie resultSet der ersten Reihe und categoryProductsResult der zweiten Reihe sehen kann die gleiche ist, aber es fügt die zweite Reihe zu resultSet.

Haben Sie Vorschläge?

+1

Zeigen Sie uns, wo Sie '.equals()' überschreiben. –

Antwort

12

Contains verwendet den Standardvergleich, der Verweise vergleicht, da Ihre Klasse Equals und GetHashCode nicht überschreibt.

class CategoryProductsResult 
{ 
    public string Name { get; set; } 
    // ... 

    public override bool Equals(object obj) 
    { 
     if(obj == null)return false; 
     CategoryProductsResult other = obj as CategoryProductsResult; 
     if(other == null)return false; 
     return other.Name == this.Name; 
    } 

    public override int GetHashCode() 
    { 
     return Name.GetHashCode(); 
    } 
} 

Jetzt können Sie einfach verwenden:

resultSet = categoryProductsResults.Distinct().ToList(); 
+1

Sehr guter Code, vielen Dank. – cagin

0

Referenzobjekte in einer Liste werden durch ihren Hash-Code indiziert. Also, Contains wird nie ein Referenzobjekt mit dem gleichen Hash-Code finden (es sei denn, Sie die GetHashCode und Equals Implementierung in der Klasse außer Kraft setzen.

Diese SO answer erklärt.

3

Liste verwendet den Vergleich von EqualityComparer.Default zurückgegeben und nach für die in der Dokumentation:

die Default-Eigenschaft überprüft, ob Typ T die System.IEquatable (Of T) -Schnittstelle, und wenn ja, gibt ein EqualityComparer (Of T) implementiert, das verwendet Implementierung. Ansonsten ist es gibt ein EqualityComparer (Of T), die die Überschreibungen von Object.Equals und Object.GetHashCode von T. bereitgestellt verwendet

So können Sie entweder implementieren IEquatable auf Ihrer benutzerdefinierten Klasse oder die Equals überschreiben (und GetHashCode), um den Vergleich anhand der von Ihnen benötigten Eigenschaften durchzuführen. Alternativ können Sie linq verwenden:

bool enthält = list.Any (i => i.Id == obj.Id);

0

Sie müssen prüfen, ob Ihr aktuelles Element wird für jede Iteration in der Zielliste enthalten. Derzeit überprüfen Sie einmal am Anfang der Schleife, was bedeutet, dass keiner Ihrer Artikel in der Zielliste ist.

Ich denke, Distinct ist bereits tun, was Sie wollen, könnten Sie diese Erweiterung anstelle Ihrer eigenen Schleife verwenden möchten.

1

Jede categoryProductsResult ist unterschiedlich zueinander. Es ist wie etwas, das Sie sehen können here.Wenn Sie ein einfacheres Produkt möchten, ist die ProductId Ihr eindeutiger Bezeichner. Führen Sie einfach den folgenden Code aus:

foreach (CategoryProductsResult categoryProductsResult in categoryProductsResults.Where(categoryProductsResult => resultSet.ProductId !=categoryProductsResult.ProductId) 
{ 
    resultSet.Add(categoryProductsResult); 
}