【问题标题】:operator== in base and Equals in derivedoperator== 在 base 和 Equals 在派生
【发布时间】:2017-06-01 04:41:48
【问题描述】:

我有一个通过引用进行比较的基类和一个通过值进行比较的派生类(仅显示此处相关的行):

class Term : IReadOnlyList<Term>
    public static bool operator ==(Term a, Term b)
    {
        if (ReferenceEquals(a, null))
            return false;
        return a.Equals(b);
    }

sealed class CompoundTerm : Term, IReadOnlyList<Term>
    public override bool Equals(object o)

所以派生类会覆盖Equals,但基类必须重载==,因为a == b 可能而且确实很可能会在ab 声明为@ 的上下文中发生987654327@但实际上指向CompoundTerm

据我所知 - 如果我错了,请纠正我 - 这是所有必要且正确的。

不幸的是,编译器对此并不满意:

Term.cs(40,11): warning CS0660: 'Term' defines operator == or operator != but does not override Object.Equals(object o)

在这里做什么最好?我可以使用禁用警告的蛮力解决方案,但我想检查并确保没有更优雅的解决方案,我缺少一些成语。

【问题讨论】:

  • “我有一个通过引用进行比较的基类” - 这不是您的基类所做的。它调用Equals,可以在派生类中重写。听起来您应该可能将Equals 重写为基类中的 abstract 方法,以强制所有子类提供实现。 (同上 GetHashCode。)(假设您也可以使您的 Term 类抽象,这似乎很可能。)
  • @JonSkeet 当然,我可以将Term 抽象化,并将AtomicTerm 派生类作为通过引用进行比较的类。在这种情况下,AtomicTerm.Equals 是必需的,但可以是只返回 ReferenceEquals(this, o)?
  • @JonSkeet 但是,在这种情况下,我该怎么办AtomicTerm.GetHashCode?是否有类似方便的方法来调用通过引用工作的默认版本?
  • 您可以使用System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(object),但是对于那种 一个 类型的术语具有引用相等性,但所有其他术语具有值相等性,这很奇怪... 另请注意您的接线员可以简化为调用Equals(a, b)。处理无效性。

标签: c# .net operator-overloading equality


【解决方案1】:

我有一个通过引用进行比较的基类和一个派生类 按值比较(仅显示相关的行 在这里)

您当前的实现不一定执行引用相等;它实际上调用了Equals 的潜在重载。

所以派生类覆盖Equals,但基类必须重载== ...

我不明白为什么,如果基类覆盖Equals,则需要在基类中重载==。如果没有定义重载,== 已经执行了引用比较,因为静态 == (object, object) 在编译时被解析。

... a == b 可能而且确实很可能出现在 a 和 b 被声明为 Term 但实际上指向 CompoundTerm 的上下文中。

ab 的真实类型在调用 == 运算符时无关紧要。 == 是一个静态方法,因此将根据参数的引用类型进行解析:

object aString = "Hello";
object theSameString = new string(new[] { 'H', 'e', 'l', 'l', 'o' }); //to avoid string interning
var referenceEquals = aString == theSameString; //false: object == object
var valueEquals = (string)aString == (string)theSameString; //true: string == string

现在我了解到您正在尝试在调用 == 时执行引用相等,如果 abTerm 而不是子类,否则执行潜在的值相等。

说实话,这似乎相当令人困惑。我建议让 == 始终执行引用相等(不要重载它),如果您需要潜在的值相等,请使用 Equals 并记录类或代码以明确此行为。

【讨论】:

    猜你喜欢
    • 2018-11-15
    • 2021-06-16
    • 2021-03-02
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多