-3

Consider:

  class Base : IEquatable<Base> {
    public bool Equals(Base other) => false;
    public override bool Equals(Object o) => false;
    public override int GetHashCode() => 0;
    public static bool operator ==(Base o1, Base o2) => Equals(o1, o2);
    public static bool operator !=(Base o1, Base o2) => !Equals(o1, o2);
  }

  class Derived : Base {
    public static bool operator ==(Derived o1, Derived o2) => Equals(o1, o2);
    public static bool operator !=(Derived o1, Derived o2) => !Equals(o1, o2);
  }

I get:

Warning CS0660  'Derived' defines operator == or operator != but does not override Object.Equals(object o)
Warning CS0661  'Derived' defines operator == or operator != but does not override Object.GetHashCode()

These warnings are to me wrong - as I inherit overridden Equals(object) and GetHashCode() from Base the code should not have any warnings.

Moreover there is no great way out of it -

I can implement the functions in Derived which is ugly and superfluous

I can add #pragma warning disable CS0660, CS0661 but that will disable the warnings everywhere in the file, not only where the functions are safely derived.

Is this an oversight of the C# compiler or is there a good reason for it ? Is there a clean way out of it ?

kofifus
  • 17,260
  • 17
  • 99
  • 173
  • 3
    Why should the compiler assume than an `Equals` on `Base` implements logic in any way associated with `operator==` on `Derived`? In fact, it quite often is an error to implement one without the other, as the logic for comparing `Derived` likely does more than `Equals` in `Base`. – Dark Falcon Jan 10 '19 at 22:02
  • 1
    No, I think it is correct. If `Base` implemented the operators, then that would be assumed correct, but since `Derived` could potentially use information unavailable to `Base.Equals` the compiler can't assume it is an appropriate match for `Derived.operator ==`, though if you defined them in terms of `Base.Equals` it should, but is too complicated. Just add overrides that define `Derived.Equals` as `Base.Equals`: `public override bool Equals(object o) => base.Equals(o);` and same for `GetHashCode`. – NetMage Jan 10 '19 at 22:03
  • nosale this is not a duplicate as my question is about when Equals and GetHashCode are correctly inherited – kofifus Jan 10 '19 at 22:10
  • `as my question is about when Equals and GetHashCode are correctly inherited` How would the compiler **know** it was 'correctly' inherited? It is quite rare for a derived class to (on purpose) use the **exact same** `Equals` / `GetHashCode` logic (after defining an explicit `==` implementation) - so the compilers mustn't have optimised for that scenario. – mjwills Jan 10 '19 at 22:14
  • 1
    The only reason to overload the operators in the derived class is because you want to change the behavior. If you have no intention of changing the behavior then *don't overload the operator* and let the base class' overload do its job. – Servy Jan 10 '19 at 22:14
  • no Servy - the _only_ reason is that static operators are not inherited ! which IMO is a c# fail – kofifus Jan 10 '19 at 22:17
  • 1
    @kofifus He asks more or less the same question as you, he could also argue like you why he gets this warnings because he inherits `Equals(object)` and `GetHashCode()` from `ValueType` – nosale Jan 10 '19 at 22:18
  • 1
    @kofifus Static members *are* inherited, if you want to be technical. Not that it really *matters* in a case like this. The operator overload exists, it'll be found when called, that's all that matters. – Servy Jan 10 '19 at 22:21
  • oh thx Servy, didn't realize that! – kofifus Jan 10 '19 at 22:23

1 Answers1

1

Computing Science often involves tradeoffs.

The tradeoff here is in thinking about the more likely mistake.

Is the more likely mistake that someone forgot to add those methods? Or is it more likely that someone inherited from another class and purposely wants to keep the implementation from the base class?

I suspect they looked at those two and thought 'well, the first scenario is more likely' - so they optimised for that scenario.

Given this is a warning, take it as such - if you disagree with it just disable (either locally, or project wide) the warning. It isn't an error.

mjwills
  • 23,389
  • 6
  • 40
  • 63