2010-04-28 1 views
5

J'ai une collection d'objets qui ont plusieurs propriétés dans chacun d'eux. J'ai souvent besoin d'obtenir une liste de valeurs distinctes pour de nombreuses propriétés de cette collection. Si j'implémente IEqualityComparer sur ce type, cela me donne un seul critère pour obtenir les objets distincts dans la collection. Comment puis-je appeler Distinct sur plusieurs critères pour cette collection?Liste <T> .Distinct() en C# - critères multiples pour EqualityComparer?

Par exemple,

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

Imaginer une liste de ces objets produits. Parfois, je veux obtenir la liste des noms distincts dans la liste, et à un autre moment, une liste de fournisseurs distincts. Si j'appelle Distinct sur une liste de ces produits, en fonction de la façon dont IEqualityComparer est implémenté, il utilisera toujours les mêmes critères, ce qui ne va pas servir à mes fins.

Répondre

13

Fournissez simplement différentes implémentations IEqualityComparer pour différents appels à Distinct. Notez la différence entre IEquatable et IEqualityComparer - généralement un type ne doit pas implémenter IEqualityComparer pour lui-même (donc Product n'implémenterait pas IEqualityComparer<Product>). Vous auriez différentes implémentations, comme ProductNameComparer, ProductCodeComparer etc.

Cependant, une autre alternative est d'utiliser DistinctBy dans MoreLINQ

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

aurait choisi comme réponse, mais pour la première réponse 2 minutes de Hans. – Bhaskar

3

Vous pouvez aussi créer un comparateur qui accepte des arguments de fonction pour les Equals et GetHashCode méthodes Quelque chose comme

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())); 
Questions connexes