9

我有一个字典,我将它与另一个字典(输入为 IDictionary 的变量)进行比较。执行 d1.Equals(d2) 会产生错误。在下面编写我自己的代码会产生正确的结果。两者都是System.Collections.Generic.Dictionary。我是否遗漏了什么或没有Dictionary比较Equals键/值的实现?

private static bool DictEquals<K, V>(IDictionary<K, V> d1, IDictionary<K, V> d2)
{
    if (d1.Count != d2.Count)
        return false;

    foreach (KeyValuePair<K, V> pair in d1)
    {
        if (!d2.ContainsKey(pair.Key))
            return false;

        if (!Equals(d2[pair.Key], pair.Value))
            return false;
    }

    return true;
}
4

5 回答 5

12

Dictionary.Equals() 使用来自 Object 的默认 Equals,检查两个对象是否是相同的引用,就像所有其他默认集合一样。您可以自由地使用值语义创建自己的子类,尽管这通常也包括不可变的事物。

于 2009-10-30T14:03:07.647 回答
5

可能该类的Equals方法Dictionary只是诉诸从 继承的默认实现Object,即它只是将Dictionary传递的对象引用与自己的引用进行比较。请参见此处:Object.Equals 参考

于 2009-10-30T14:00:24.267 回答
2

假设两个字典,一个是 aSortedList<TKey, TValue>和一个 a Dictionary<TKey, TValue>,比较是否相等,如果项目相同,它真的应该返回 true 吗?那会很糟糕,因为它们具有不同的特性和特性(SortedList<,>例如允许通过索引进行检索)。

此外,相等和哈希码在逻辑上是联系在一起的。哈希码应该是不可变的,否则所有基于哈希的算法都将不起作用。当您使用内容检查是否相等时,您无法保证这一点。因此,默认实现(检查它们是否是同一个实例)非常合理。不过,您可以自由创建自己的内容平等比较。

于 2009-10-30T14:13:35.190 回答
1

其他人提到它正在使用 Object.Equals 实现,您可以使用以下内容覆盖它:

public class EqualsDictionary<T, T> : Dictionary<T, T>
{
    public override bool Equals(object obj)
    {
        //Place your comparison implementation here
    }
}
于 2009-10-30T14:11:56.223 回答
0

除了封装对象状态的不可变方面之外,.NET 中的引用还可用于封装对象的标识、其状态的可变方面,或者两者都封装或都不封装。一般来说,如果没有特别的理由来假设,.NET 假设对可变对象的引用用于封装标识的目的。它进一步假设,在代码比较引用而不知道它们代表什么的情况下,最好在报告不相等的情况下犯错。因此,当且仅当它们标识同一个对象时,对可变对象的两个引用通常被认为是等效的,因此不鼓励可变类型覆盖Equals以指示其他任何内容。相反,使用引用来封装可变状态的代码应该使用除Object.Equals()比较它们。

于 2013-11-03T20:42:55.630 回答