【问题标题】:.Net Dictionary and the Overriding of Equals.Net 字典和等于的覆盖
【发布时间】:2010-11-23 23:17:41
【问题描述】:

我知道,当我创建一个以自定义类作为键的字典时,我提供键时的匹配是通过引用比较完成的。例如:

public class SomeClass
{
    public object SomeValue { get; set; }
}

// ....
public static void Main()
{
    var dict = new Dictionary<SomeClass, string>();

    var key1 = new SomeClass { SomeValue = 30 };
    dict[key1] = "30";

    Console.WriteLine(dict[key1]); // prints "30"

    var key2 = new SomeClass { SomeValue = 30 };
    Console.WriteLine(dict[key2]); // prints null 
}

如果我在 SomeClass 类中覆盖 Equals(和 ==)会发生什么?我会在输出的第二行得到“30”吗?

如果我想要一个基于引用而不是成员值的字典,但我已经覆盖了 Equals,该怎么办?

谢谢!!

【问题讨论】:

    标签: .net dictionary


    【解决方案1】:

    简答

    是的,如果您覆盖 EqualsGetHashCode 方法,您的自定义键比较将开始工作。

    长答案

    Dictionary&lt;TKey,TValue&gt; 类不一定会进行基于引用的比较。它改为使用可以提供给构造函数的IEqualityComparer&lt;TKey&gt; 实例。如果未提供,则默认为 EqualityComparer&lt;T&gt;.Default

    EqualityComparer&lt;T&gt;.Default 工作的过程很复杂。但总结是

    • 在类型上查找IEquatable&lt;T&gt;,如果存在则用于相等
    • 默认使用Equals 方法,默认为Object.Equals,因此是参考比较

    因此类型可以覆盖几个级别的比较

    • 通过指定自定义IEqualityComparer&lt;T&gt;
    • 实现IEquatable&lt;T&gt; 并覆盖GetHashCode
    • 覆盖EqualsGetHashCode

    等式运算符==!=Dictionary&lt;TKey,TValue&gt; 中的TKey 类型不起作用。

    【讨论】:

    • 您的长答案可能应该重申一下关于 GetHashCode 的内容。如果哈希码不匹配,您所描述的都不会发生。
    • @Joe 将GetHashCode 部分添加到IEquatable&lt;T&gt; 讨论中。
    • @Jon Skeet:最佳实践要求其基类型实现其(基类)自己类型的 iEquatable 的任何派生类覆盖它,除了实现其(派生类)的 iEquatable自己的类型?这似乎是相当多的额外工作,如果缺少类型,则很可能会出现故障(因为可能会调用基类的 iEquatable 实现而不是派生的实现)。
    • @supercat:类型层次结构中的平等基本上是混乱的。遵守 equals 约定需要检查另一个对象是否完全您的类型,否则很难自反地工作。对于非密封类,我更喜欢使用显式 IEqualityComparer - 这样您就可以以任何方式进行比较。
    • @Bruno Brant:iEqualityComparer 可以简单地调用它自己的 Equals 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多