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

时间:2010-04-28 15:05:36

标签: c# list distinct

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

例如,

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

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

3 个答案:

答案 0 :(得分:14)

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

但是,另一种方法是在DistinctBy

中使用MoreLINQ
var distinctProducts = products.DistinctBy(p => p.name);

答案 1 :(得分:6)

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

答案 2 :(得分: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()));