2012-08-09 15 views
12

Ich habe folgende Linq Ausdruck:Distinct() funktioniert nicht

AgentsFilter = new BindableCollection<NameValueGuid>((
    from firstEntry in FirstEntries 
    select new NameValueGuid { 
     Name = firstEntry.Agent, 
     Value = firstEntry.AgentId 
    }).Distinct() 
); 

Aber wegen irgendeinem Grund ist die AgentsFilter Sammlung von Duplikaten voll. Was ist los mit meinem Distinct()?

Antwort

28

Distinct verwenden Sie die Equals Methode auf NameValueGuid, um Duplikate zu finden. Wenn Sie Equals nicht überschreiben, überprüft es Referenzen.

Sie können einen zusätzlichen Schritt hinzufügen, um das Überschreiben von Equals zu vermeiden, indem Sie einen anonymen Typ verwenden. Anonyme Typen überschreiben Equals und GetHashCode automatisch, um jedes Mitglied zu vergleichen. Wenn Sie das Distinct auf den anonymen Typ anwenden, wird das Problem durch die Projektion auf Ihre Klasse gelöst.

from firstEntry in FirstEntries 
select new 
{ 
    Name = firstEntry.Agent, 
    Value = firstEntry.AgentId 
}).Distinct().Select(x => new NameValueGuid 
{ 
    Name = x.Name, 
    Value = x.Value 
}); 
+0

Vielen Dank und alle anderen, die geantwortet haben. –

+1

Stimmen Sie ab für 'Distinct verwendet die Equals-Methode, um Duplikate zu finden. Wenn Sie Equals nicht überschreiben, werden die Referenzen überprüft. –

7

Sie keine Implementierung von sowohl GetHashCode und Equals auf NameValueGuid geliefert haben könnte. Wenn das nicht möglich ist, können Sie alternativ eine Instanz IEqualityComparer<NameValueGuid> an Ihren Anruf von Distinct übergeben.

See: http://msdn.microsoft.com/en-us/library/system.linq.enumerable.distinct.aspx

+0

Gute Erklärung, aber es gibt eine andere Lösung: Verwendung von anonymen Typen (siehe * Cadrell0 * 's Antwort) –

+0

+1, erkannte nicht, dass ich 'GetHashCode' auch überschreiben musste, damit' Distinct' funktioniert. Nach dem Überschreiben scheint es, dass "Distinct" zuerst "GetHashCode" aufruft, um zu bestimmen, ob es "Equals" aufrufen muss. – DCShannon

4

Sie müssen definieren, was Distinct bedeutet im Rahmen einer Klasse mit Name und Value Eigenschaften. Siehe MSDN.

Versuchen Sie die Überladung von Distinct, die Sie einen Vergleich bereitstellen können.

Zum Beispiel:

AgentsFilter = new BindableCollection<NameValueGuid>((from firstEntry in FirstEntries 
    select new NameValueGuid 
    { 
     Name = firstEntry.Agent, 
     Value = firstEntry.AgentId 
    }) 
    .Distinct((nvg) => nvg.Value) 
); 

Alternativ, wenn Sie Zugriff auf den Code Definition von NameValueGuid haben, dann können Sie außer Kraft setzen GetHashCode und Equals wie für die Klasse geeignet ist. Siehe auch MSDN

4
select new 
{ 
    Name = firstEntry.Agent, 
    Value = firstEntry.AgentId 
}) 
.Distinct() 
.Select(x => new NameValueGuid 
{ 
    Name = x.Name, 
    Value = x.Value 
});