为什么C#中的Dictionary有一个.Distinct()扩展名?

时间:2013-07-17 17:05:21

标签: c# dictionary

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

5 个答案:

答案 0 :(得分:8)

Dictionary<TKey, TValue>实施IEnumerable<KeyValuePair<TKey, TValue>>,其扩展名为DistinctDictionary类本身没有Distinct

的实现

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

Enueramble.Distinct(IEnumerable<T> source)

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

答案 1 :(得分:4)

Distinct适用于IEnumerable<KeyValuePair<TKey, TValue>>的{​​{1}}界面。虽然它没有意义,因为字典具有唯一键,但扩展名仅因Dictionary<TKey, TValue>实现Dictionary<TKey, TValue>而存在。

答案 2 :(得分:3)

Distinct()扩展方法在dictinoary上不是具体,而是任何IEnumerable<T>

由于Dictionary<T,U>IEnumerable<KeyValuePair<T,U>>,它会获得此方法,即使它不一定适合此类。

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

答案 3 :(得分:1)

Dictionary<TKey, TValue>实现了IEnumerable<KeyValuePair<TKey, TValue>>,而DistinctIEnumerable<T>的扩展方法,所以它是免费提供的,无论它是否有用。

您是正确的,只要Distinct使用与IEqualityComparer相同的Dictionary,在技术上就不可能在该特定序列中包含任何重复的对象。如果您为Distinct方法提供的自定义 IEqualityComparer使用与Dictionary使用的不同的相等定义,那么{{1}确实可能找到重复的文件。

答案 4 :(得分: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(),但没有。 Microsoft 可以Distinct内进行一些切换,以确定我们是否在任何基于散列的集合中。但是,这不会给该方法带来任何好处。实际上它甚至返回了预期的元素(上例中的所有三个元素)。