2

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

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正如 Konrad Rudolph 指出的那样,我想这将引入集合的约束,即仅持有实现的对象。但是,在像 Dictionary 这样的对象中,这似乎并不过分要求。

4

3 回答 3

2

Dictionary<T,T>.Equals是从 Object.Equals 继承的,因此对对象引用进行了简单的比较。

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

因此,如果有必要,您可以提供一些其他语义。

于 2008-12-22T22:24:09.420 回答
2

换句话说,为什么没有内置的方法来为泛型集合做值相等?

可能是因为很难用通用术语来表述,因为这只有在字典的值类型(和键类型)也实现的情况下才有可能IEquatable。但是,要求这个太强了,使得Dictionary许多没有实现这个接口的类型无法使用。

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

请注意,与容器相比,类似的情况是正确的IComparable,但对此有支持,Comparer<T>.Default如有必要,请使用。

于 2008-12-22T22:25:35.283 回答
1

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

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

在我看来,让两个对象相互比较是一件相当特别的事情,因此将其放入接口中比仅在基 Object 类中放入默认的通常不需要的实现更有意义。它应该是一个类的一个比每个对象都可以做的更广为宣传的特性,尽管它不是你期望的那样。

但是你现在有了。它就在那里,您需要知道何时使用它。

就像在这种情况下。

于 2008-12-22T22:25:32.193 回答