List<T>.Distinct() in C# - multiple criteria for EqualityComparer?
I have a collection of objects which have several properties in each of them. I often need to get a list of distinct values for many properties in this collection. If I implement IEqualityComparer on this type , it gives me one single criteria for getting the distinct objects in the collection. How do I get to be able to call Distinct on multiple criteria for this collection ?
For example ,
class Product {
string name ;
string code ;
string supplier ;
//etc
}
Imagine a list of such product objects. Someti开发者_开发问答mes , I want to get list of distinct names in the list , and at some oter time , a list of distinct supplier . etc. If I call Distinct on a list of these products , based on the way IEqualityComparer is implemented , it will always use the same criteria , which is not going to serve my purpose.
Simply provide different IEqualityComparer
implementations for different calls to Distinct
. Note the difference between IEquatable
and IEqualityComparer
- usually a type shouldn't implement IEqualityComparer
for itself (so Product
wouldn't implement IEqualityComparer<Product>
). You'd have different implementations, such as ProductNameComparer, ProductCodeComparer etc.
However, another alternative is to use DistinctBy
in MoreLINQ
var distinctProducts = products.DistinctBy(p => p.name);
You can use the Distinct() overload that accepts an IEqualityComparer argument.
You could also create a comparer that accepts function arguments for the Equals and GetHashCode methods. Something like
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()));
精彩评论