operator== in base 和 Equals in derived

operator== in base and Equals in derived

提问人:rwallace 提问时间:1/17/2017 更新时间:1/17/2017 访问量:716

问:

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

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 == babTermCompoundTerm

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

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

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

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

C# .NET 运算符重载 相等

评论

4赞 Jon Skeet 1/17/2017
“我有一个通过引用进行比较的基类”——这不是你的基类的作用。它调用 ,可以在派生类中重写。听起来你应该在基类中作为抽象方法进行重写,以强制所有子类提供实现。(同上 GetHashCode。(这是假设你也可以让你的类抽象化,这似乎很有可能。EqualsEqualsTerm
0赞 rwallace 1/17/2017
@JonSkeet 当然,我可以使抽象类并使派生类成为通过引用进行比较的类。在这种情况下,是必需的,但可以是只返回的单行代码?TermAtomicTermAtomicTerm.EqualsReferenceEquals(this, o)
0赞 rwallace 1/17/2017
@JonSkeet 但是,在这种情况下,我该怎么办?有没有一种同样方便的方法来调用通过引用工作的默认版本?AtomicTerm.GetHashCode
1赞 Jon Skeet 1/17/2017
你可以用 ,但是很奇怪的是,只有一种术语具有引用相等性,而所有其他术语都具有价值相等性......另请注意,您的操作员可以简化为调用 .这处理了无效性。System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(object)Equals(a, b)

答:

0赞 InBetween 1/17/2017 #1

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

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

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

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

...在将 a 和 b 声明为 Term 但实际上指向 CompoundTerm 的上下文中,a == b 可能会发生,而且确实很有可能。

呼叫操作员时,真正的类型和是什么无关紧要。 是一个静态方法,因此将根据参数的引用类型进行解析: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

现在,我理解您正在尝试的正是在调用 if 和 are 和 not 子类时执行引用相等,否则执行潜在的值相等。==abTerm

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