【问题标题】:Equals override vs. IEquatable<> [duplicate]等于覆盖与 IEquatable<> [重复]
【发布时间】:2016-12-19 15:57:18
【问题描述】:

在我的一生中,我无法让我的 WPF 绑定为 RibbonComboBoxSelectedItem 属性正常工作。

然后我开始阅读 .NET 如何比较项目。我的理解是,在某些情况下,它会比较实际的指针。在这种情况下,从数据库中加载一个新的相等的值,例如,它可能不被认为是相等的。

然后我开始研究为我的类型显式实现Equals。但是,这似乎有点令人困惑,因为我至少可以实现两个不同的版本。

下面的代码显示我可以覆盖object.Equals,也可以实现IEquatable&lt;&gt;。事实上,下面的代码实现了两者,并且测试表明两者都被调用

public class TextValuePair : IEquatable<TextValuePair>
{
    public string Text { get; set; }
    public int Value { get; set; }

    public override bool Equals(object obj)
    {
        if (obj == null || !(obj is TextValuePair))
            return false;
        return Value == (obj as TextValuePair).Value;
    }

    public override int GetHashCode()
    {
        return Value;
    }

    public bool Equals(TextValuePair obj)
    {
        Debug.Assert(obj != null);
        if (obj == null)
            return false;
        return Value == obj.Value;
    }
}

有人可以帮助我了解如何避免我的对象被 .NET 库例程根据具有相同值的指针进行等价比较吗?真的有必要实现Equals的两个版本吗?

【问题讨论】:

  • 它们是实现Equals 的许多可能方式,但您为什么不直接选择override Equals,因为它将始终使用。它不适用于您的情况吗?
  • 是的,等式的东西在 .NET 中有点乱,并不是所有的库都以相同的方式调用 Equals 方法。为了进一步帮助您,您需要发布有关代码绑定部分的更多信息,以查看涉及哪些库调用。此外,为了完整起见,我将仅提及基于可变属性的哈希码是危险的。希望这与您的问题无关。
  • 您可以将第一个Equals() 实现为:public override bool Equals(object obj) { return Equals(obj as TextValuePair); },只要您正在实现IEquatable&lt;TextValuePair&gt;
  • 如果你不实现IEquatable&lt;T&gt;Equals(object) 的覆盖总是会被调用。 IEquatable&lt;T&gt; 是首选,因为它更精确且性能更好。

标签: c# wpf equals iequatable


【解决方案1】:

正如msdn 所指出的,如果您正在实现IEquatable&lt;T&gt;,您仍然需要覆盖Equals,因为它仍将使用签名Equals(System.Object, System.Object) 调用,并且您的覆盖应该与从@ 实现的方法一致987654326@。

与 Arno 在评论中显示的 question about the difference between iequatable and just overriding object equals 一样,IEquatable&lt;T&gt; 用于需要对集合进行操作以优化它们,不再需要装箱,而是调用具有特定类型的直接 Equals 时使用。

你有两个选择:

如果您在程序中处理集合时对性能感兴趣,您可以继续实现Equals 方法;

您可以删除 IEquatable&lt;T&gt; 并仅覆盖 Equals 以简化您的代码。

此外,无论何时覆盖Equals,您也应该始终覆盖GetHashCode

【讨论】:

  • 是的,看起来object.Equals() 曾经是覆盖比较的唯一方法。但由于它需要装箱值类型,因此添加了较新的 IEquatable&lt;&gt; 以更快。出于性能原因,您似乎应该同时实现两者。但是,当你说它仍然会用签名Equals(System.Object, System.Object)调用时,你知道那个版本被调用的是什么情况吗?
  • @JonathanWood 这也是一个很好的问题,如果你这样做Object.Equals(objectA, objectB) 就会被调用,它可以围绕不同的类型进行装箱,并且它们仍然可以相等,对于给定的 Equals 覆盖和如果它们具有相同的属性。
猜你喜欢
  • 2014-12-31
  • 2012-02-16
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 2014-02-09
  • 2016-05-31
  • 2014-04-20
相关资源
最近更新 更多