2010-04-28 13 views
5

Ho una collezione di oggetti che hanno diverse proprietà in ognuno di essi. Spesso ho bisogno di ottenere un elenco di valori distinti per molte proprietà in questa raccolta. Se implemento IEqualityComparer su questo tipo, mi dà un singolo criterio per ottenere gli oggetti distinti nella raccolta. Come posso essere in grado di chiamare Distinct su più criteri per questa raccolta?Elenco <T> .Distinct() in C#: più criteri per EqualityComparer?

Per esempio,

class Product { 
    string name ; 
    string code ; 
    string supplier ; 
//etc 
} 

Immaginate un elenco di tali oggetti prodotto. A volte, desidero ottenere l'elenco di nomi distinti nell'elenco e, in un altro momento, un elenco di fornitori distinti. ecc. Se chiamo Distinto in un elenco di questi prodotti, in base al modo in cui viene implementato IEqualityComparer, verrà sempre utilizzato lo stesso criterio, che non verrà utilizzato per il mio scopo.

risposta

13

È sufficiente fornire diverse implementazioni IEqualityComparer per diverse chiamate a Distinct. Notare la differenza tra IEquatable e IEqualityComparer - in genere un tipo non deve implementare IEqualityComparer per se stesso (quindi Product non implementerà IEqualityComparer<Product>). Avresti diverse implementazioni, come ProductNameComparer, ProductCodeComparer ecc

Tuttavia, un'altra alternativa è quella di utilizzare DistinctBy in MoreLINQ

var distinctProducts = products.DistinctBy(p => p.name); 
+0

avrebbe scelto come risposta, ma per la 2 minuti risposta iniziale da Hans. – Bhaskar

3

Si potrebbe anche creare un operatore di confronto che accetta gli argomenti delle funzioni per le Equals e GetHashCode metodi. Qualcosa di simile

class Foo 
{ 
    public string Name { get; set; } 
    public int Id { get; set; } 
}  

class FooComparer : IEqualityComparer<Foo> 
{ 
    public FooComparer(Func<Foo, Foo, bool> equalityComparer, Func<Foo, int> getHashCode) 
    { 
     EqualityComparer = equalityComparer; 
     HashCodeGenerator = getHashCode; 
    } 

    Func<Foo, Foo, bool> EqualityComparer; 
    Func<Foo, int> HashCodeGenerator; 

    public bool Equals(Foo x, Foo y) 
    { 
     return EqualityComparer(x, y); 
    } 

    public int GetHashCode(Foo obj) 
    { 
     return HashCodeGenerator(obj); 
    } 
} 

...

List<Foo> foos = new List<Foo>() { new Foo() { Name = "A", Id = 4 }, new Foo() { Name = "B", Id = 4 } }; 
var list1 = foos.Distinct(new FooComparer((x, y) => x.Id == y.Id, f => f.Id.GetHashCode())); 
Problemi correlati