System.Collections.Generic.Dictionary <t,t> .Equals实际上做了什么?</t,t>

时间:2008-12-22 22:20:02

标签: c# generics collections comparison equality

今天我在单元测试通用字典时遇到了这个问题。

System.Collections.Generic.Dictionary<int, string> actual, expected;
actual = new System.Collections.Generic.Dictionary<int, string> { { 1, "foo" }, { 2, "bar" } };
expected = new System.Collections.Generic.Dictionary<int, string> { { 1, "foo" }, { 2, "bar" } };
Assert.AreEqual(expected, actual); //returns false

失败,除非actual == expected(对象引用相同)。显然,actual.Equals(expected)也会返回false。

很好,但是如果System.Collections.Generic.Dictionary<int, string>.Equals的实现只引用了相等性,那么IEquatable的重点是什么?换句话说,为什么没有实用的方法来为泛型集合进行值相等?

修改感谢您的回复。显然我的例子是使用值类型,但我认为我的抱怨适用于所有对象。为什么泛型集合平等不能仅仅是其类型的等式联合?意外的行为并没有真正削减它,因为有单独的条款来寻找参考平等。康拉德鲁道夫指出,我认为这会引入只包含实现IEquatable的对象的集合约束。但是,在像Dictionary这样的对象中,这似乎没有太多要求。

3 个答案:

答案 0 :(得分:2)

Dictionary<T,T>.Equals继承自Object.Equals,因此可以对对象引用进行简单比较。

为什么泛型集合不能进行值相等的语义?因为那可能不是你想要的。有时你想检查它们是否是同一个实例。替代方案会做什么?在每个键和值上调用Equals?如果这些从对象继承Equals怎么办?这不是一个完整的深度比较。

因此,如果需要,您可以提供其他语义。

答案 1 :(得分:2)

  

换句话说,为什么没有通用的方法来为泛型集合进行值相等?

可能因为很难用通用术语表达,因为只有在字典的值类型(和键类型)也实现IEquatable时才可能这样做。但是,要求这样做会太强大,导致Dictionary无法使用许多未实现此接口的类型。

这是受约束的泛型的固有问题。 Haskell为这个问题提供了一个解决方案,但这需要一个更强大,更复杂的泛型机制。

请注意,与容器相比,IComparable会发生类似情况,但如果需要,可以使用Comparer<T>.Default支持此功能。

答案 2 :(得分:1)

Dictionary<TKey, TValue>没有实现IEquatable,因此没有正式的方法可以确定/知道将一个这样的字典与另一个字典进行比较,实际产生的内容是否相同。

实际上,Dictionary<TKey, TValue>根本没有实现任何比较接口。

在我看来,让两个对象进行自我比较是一件相当特别的事情,因此将它放入一个接口比将一个默认的通常不需要的实现放在基类Object中更有意义。它应该是一个更广告的类的功能,而不是每个对象可以做的事情,虽然不是你期望它的方式。

但是你有它。它就在那里,你需要知道什么时候会被使用。

就像这种情况一样。