2

正如标题所说,为什么 C# 中的 Dictionary 集合包含一个 .Distinct() 扩展名,就好像 Dictionary 可能包含非不同的键一样?这背后是否有合理的理由,还是我读得太深了?

4

5 回答 5

8

Dictionary<TKey, TValue>IEnumerable<KeyValuePair<TKey, TValue>>具有Distinct扩展名的工具。类Dictionary本身没有实现Distinct

调用Distinct被转换为对静态扩展方法的调用:

Enueramble.Distinct(IEnumerable<T> source)

这是不必要的,Dictionary因为键是不同的(因此键/值对是不同的),但从技术上讲它没有任何问题。

于 2013-07-17T17:07:18.187 回答
4

Distinct应用于从 a的IEnumerable<KeyValuePair<TKey, TValue>>接口Dictionary<TKey, TValue>。虽然它没有意义,因为字典具有唯一的键,但扩展将仅因为Dictionary<TKey, TValue>implements而存在IEnumerable<KeyValuePair<TKey, TValue>>

于 2013-07-17T17:07:42.737 回答
3

Distinct()扩展方法不是专门针对 dictinoary的,而是 any IEnumerable<T>.

因为Dictionary<T,U>is an IEnumerable<KeyValuePair<T,U>>,所以它得到这个方法,即使它不一定适合这个类。

这是扩展方法的一个缺点——它们“扩展”任何适合第一个参数的类,无论该特定类是否合适。

于 2013-07-17T17:08:28.497 回答
1

Dictionary<TKey, TValue>实现IEnumerable<KeyValuePair<TKey, TValue>>,并且Distinct是 的扩展方法IEnumerable<T>,所以它是免费提供的,不管它是否有用。

您是对的,只要Distinct使用IEqualityComparerDictionary. 如果您为该Distinct方法提供一个自定义 IEqualityComparer,该自定义使用的相等定义与所使用的定义不同,Dictionary那么确实可以Distinct找到重复项。

于 2013-07-17T17:07:36.627 回答
0

我添加了之前没有提到的另一个方面。正如其他人提到的,Distinct这实际上是IEnumerable<T>. 但是,还有第二个期望IEqualityComparer<T>. 现在您可以编写以下代码:

class Program
{
    static void Main(string[] args)
    {
        var map = new Dictionary<int, int> { { 1, 1 }, { 2, 1 }, { 3, 1 } };
        var result = map.Distinct(new MyComparer());
    }

    class MyComparer : IEqualityComparer<KeyValuePair<int, int>>
    {
        public bool Equals(KeyValuePair<int, int> x, KeyValuePair<int, int> y)
        {
            return x.Value == y.Value;
        }

        public int GetHashCode(KeyValuePair<int, int> obj)
        {
            return 1;
        }
    }
}

该程序将返回KeyValuePair字典中的第一个,因为映射中的所有 都是相等的。当然有更好的方法来实现这一点。

现在你有了Dictionary<U, V>.Distinct(IEqualityComparer<U, V>),确实有一些实际用途,如上所示 - 和Disitinct(), 没有。微软本可以在内部进行一些切换,Distinct以确定我们是否在任何基于散列的集合中。但是,这不会为该方法增加任何好处。事实上,它甚至会返回预期的元素(上例中的所有三个元素)。

于 2018-04-05T10:38:45.913 回答