Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why no warning for GetHashCode() without Equals()

Tags:

c#

I apologize for the shortness of the title, but the actual title would be a bit too long. Here is the actual long title:

Why a warning when overriding Equals() without GetHashCode() but no warning when overriding GetHashCode() without Equals()?

I also apologize in advance about the fact that this is not a "What is the X of Y" type of question, it is more of an "I observed X; am I missing something?" type of question.

So, consider the following:

class A
{
    public override bool Equals( object other ) => true; //warning CS0659
}

class B
{
    public override int GetHashCode() => 42; //No warning
}

I am aware of the reasons behind warning CS0659 "class overrides Object.Equals(object o) but does not override Object.GetHashCode()". I do not agree with those reasons, because Equals() is perfectly viable for a mutable class, whereas such a class must of course never be used as a key in a hash map, and therefore must not have a GetHashCode(), but my objections are irrelevant, and in any case, receiving a warning which you have no need for is never a problem, because you can always disable it.

It is, however, a problem when you can think of a warning that you would have a use for, but you are not receiving such a warning.

This is what class B above demonstrates. Overriding GetHashCode() without also overriding Equals() is almost certainly a grave mistake, and yet there is no warning. Not by the C# compiler, nor by ReSharper.

Does anyone know why?

Is there something I am missing?

Could it be that the warning exists, but I must know some configuration magic to tease it out of the compiler?

Could it be that I must declare my class in some weird way like public sealed albino or something?

Are there any legitimate reasons for the absence of the warning?

EDIT

So far there have been a few answers to this question and they all pretty much state the same thing: there is no warning because there is no violation of the contract for GetHashCode() and Equals().

Ladies and gentlemen, you are missing the point.

(Or maybe I should say I apologize for failing to make the point more clear.)

The "no violation of contract" argument in support of the absence of this warning makes about as much sense as trying to support the absence of some other warning, like "event is never used", on the grounds that by declaring an event and never using it you are not violating any contract either.

Well, first of all, if I was violating some contract by declaring an event and never using it, I would expect an error, not a warning.

But most importantly, declaring an event and never using it is a grave and insidious mistake, so it needs a warning, regardless of contracts.

And in fact, there is a warning for it!

It is CS0067 "The event '{0}' is never used".

See? warnings do not require any contracts to be violated.

So that argument is blown out of the water.

Any other arguments, please?

like image 653
Mike Nakis Avatar asked Sep 07 '25 00:09

Mike Nakis


1 Answers

The GetHashCode() method should reflect the Equals logic; the rules are:

  • if two things are equal (Equals(...) == true) then they must return the same value for GetHashCode()
  • if the GetHashCode() is equal, it is not necessary for them to be the same; this is a collision, and Equals will be called to see if it is a real equality or not.
like image 70
Mykhailo Nohas Avatar answered Sep 10 '25 02:09

Mykhailo Nohas