开发者

List<T>.Distinct() in C# - multiple criteria for EqualityComparer?

开发者 https://www.devze.com 2022-12-28 17:15 出处:网络
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 t

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()));
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号