对,所以我有一个可枚举的,希望从中得到不同的值。

使用System.Linq,当然有一个名为Distinct的扩展方法。在简单的情况下,它可以不带参数使用,例如:

var distinctValues = myStringList.Distinct();

很好,但如果我有一个可枚举的对象,需要为其指定相等,唯一可用的重载是:

var distinctValues = myCustomerList.Distinct(someEqualityComparer);

相等比较器参数必须是IEqualityComparer<T>的实例。当然,我可以做到这一点,但这有点冗长,而且,嗯,包含了很多内容。

我所期望的是一个重载,它会接受lambda,比如Func<T,T,bool>:

var distinctValues = myCustomerList.Distinct((c1, c2) => c1.CustomerId == c2.CustomerId);

有人知道是否存在这样的扩展,或者是否存在等效的解决方法?还是我错过了什么?

或者,有没有一种方法可以内联指定IEqualityComparer(让我尴尬)?

使现代化

我在MSDN论坛上找到了Anders Hejlsberg对此主题的回复。他说:

您将遇到的问题是,当两个对象进行比较时相等,它们必须具有相同的GetHashCode返回值(或Distinct内部使用的哈希表将无法正常工作)。我们使用IEqualityComparer,因为它包兼容Equals和GetHashCode的实现集成到单个接口中。

我想这是有道理的。


当前回答

如果Distinct()不能产生唯一的结果,请尝试以下方法:

var filteredWC = tblWorkCenter.GroupBy(cc => cc.WCID_I).Select(grp => grp.First()).Select(cc => new Model.WorkCenter { WCID = cc.WCID_I }).OrderBy(cc => cc.WCID); 

ObservableCollection<Model.WorkCenter> WorkCenter = new ObservableCollection<Model.WorkCenter>(filteredWC);

其他回答

速记解决方案

myCustomerList.GroupBy(c => c.CustomerId, (key, c) => c.FirstOrDefault());

在.NET 6或更高版本中,有一个新的内置方法Enumerable.DistinctBy来实现这一点。

var distinctValues = myCustomerList.DistinctBy(c => c.CustomerId);

// With IEqualityComparer
var distinctValues = myCustomerList.DistinctBy(c => c.CustomerId, someEqualityComparer);

如果Distinct()不能产生唯一的结果,请尝试以下方法:

var filteredWC = tblWorkCenter.GroupBy(cc => cc.WCID_I).Select(grp => grp.First()).Select(cc => new Model.WorkCenter { WCID = cc.WCID_I }).OrderBy(cc => cc.WCID); 

ObservableCollection<Model.WorkCenter> WorkCenter = new ObservableCollection<Model.WorkCenter>(filteredWC);

这里有一个简单的扩展方法,可以满足我的需要。。。

public static class EnumerableExtensions
{
    public static IEnumerable<TKey> Distinct<T, TKey>(this IEnumerable<T> source, Func<T, TKey> selector)
    {
        return source.GroupBy(selector).Select(x => x.Key);
    }
}

遗憾的是,他们没有将这样的独特方法烘焙到框架中,但嘿嘿。

Microsoft System.Interactive包具有一个采用密钥选择器lambda的Distinct版本。这实际上与Jon Skeet的解决方案相同,但它可能有助于人们了解并查看图书馆的其他部分。