首页 文章

在C#中列出<T> .Distinct() - EqualityComparer的多个标准?

提问于
浏览
5

我有一组对象,每个对象都有几个属性 . 我经常需要获取此集合中许多属性的不同值列表 . 如果我在这种类型上实现IEqualityComparer,它给了我一个标准来获取集合中的不同对象 . 如何在此系列的多个条件上调用Distinct?

例如 ,

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

想象一下这样的产品对象列表 . 有时候,我希望在列表中获得不同名称的列表,并在某个时间列出不同供应商的列表 . 如果我在这些产品的列表上调用Distinct,基于IEqualityComparer的实现方式,它将始终使用相同的标准,这不符合我的目的 .

3 回答

  • 6

    您可以使用接受IEqualityComparer参数的Distinct() overload .

  • 14

    只需为 Distinct 的不同调用提供不同的 IEqualityComparer 实现 . 注意 IEquatableIEqualityComparer 之间的区别 - 通常一个类型不应该为自己实现 IEqualityComparer (所以 Product 不会实现 IEqualityComparer<Product> ) . 您将拥有不同的实现,例如ProductNameComparer,ProductCodeComparer等 .

    但是,另一种方法是在MoreLINQ中使用DistinctBy

    var distinctProducts = products.DistinctBy(p => p.name);
    
  • 3

    您还可以创建一个接受Equals和GetHashCode方法的函数参数的比较器 . 就像是

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

相关问题