为什么C#中的Dictionary有.Dispinct()扩展名
本文关键字:扩展名 Dispinct 中的 Dictionary 为什么 | 更新日期: 2023-09-27 18:22:48
正如标题所说,为什么C#中的Dictionary集合包含.Dispinct()扩展名,就好像Dictionary可以包含非不同的键一样?这背后有正当的理由吗?还是我读得太多了?
Dictionary<TKey, TValue>
实现了具有Distinct
扩展的IEnumerable<KeyValuePair<TKey, TValue>>
。Dictionary
类本身没有Distinct
的实现
调用Distinct
被转换为对静态扩展方法的调用:
Enueramble.Distinct(IEnumerable<T> source)
这对Dictionary
来说并不奇怪,因为键是不同的(因此键/值对是不同的),但从技术上讲没有错
Distinct
从Dictionary<TKey, TValue>
应用于IEnumerable<KeyValuePair<TKey, TValue>>
接口。虽然这没有意义,因为字典有唯一的键,但扩展将仅因为Dictionary<TKey, TValue>
实现了IEnumerable<KeyValuePair<TKey, TValue>>
而存在。
Distinct()
扩展方法不是dictionary上的特定,而是任何IEnumerable<T>
。
由于Dictionary<T,U>
是IEnumerable<KeyValuePair<T,U>>
,所以它得到了这个方法,即使它不一定适合这个类。
这是扩展方法的一个缺点——它们"扩展"任何符合第一个参数的类,无论该特定类是否合适。
Dictionary<TKey, TValue>
实现了IEnumerable<KeyValuePair<TKey, TValue>>
,而Distinct
是IEnumerable<T>
的一个扩展方法,因此无论它是否有用,它都是免费提供的。
您是正确的,只要Distinct
使用与Dictionary
相同的IEqualityComparer
,在该特定序列中就不可能有任何重复的对象。如果给Distinct
方法一个自定义IEqualityComparer
,该方法使用与Dictionary
不同的相等定义,则Distinct
确实有可能找到重复项。
我添加了另一个以前没有提到的方面。正如其他人所提到的,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
中进行一些切换,以确定我们是否在任何基于哈希的集合中。然而,这不会给这种方法带来任何好处。事实上,它甚至返回期望的元素(在上面的例子中,这三个元素都是)。