When implementing IEqualityComparer Should GetHashCode check for null?

When implementing IEqualityComparer<Product> ( Product is a class), ReSharper complains that the null check below is always false:

 public int GetHashCode(Product product) { // Check whether the object is null. if (Object.ReferenceEquals(product, null)) return 0; // ... other stuff ... } 

(Sample code from MSDN VS.9 Documentation for Enumerable.Except )

ReSharper may be wrong, but when searching for an answer, I came across the official documentation for IEqualityComparer<T> , which has an example where null is not checked:

 public int GetHashCode(Box bx) { int hCode = bx.Height ^ bx.Length ^ bx.Width; return hCode.GetHashCode(); } 

In addition, the documentation for GetHashCode() states that ArgumentNullException will be thrown when "obj is a reference type and obj is null."

So, when implementing IEqualityComparer , GetHashCode should check for null, and if so, what should it do with null (throw an exception or return a value)?

What interests me most is the official .NET Framework documentation, which somehow indicates if null should be checked.

+7
c # hash
source share
3 answers

ReSharper is wrong.

Obviously, the code you write can call this particular GetHashCode method and pass null . All known methods can guarantee that this will never happen, but, obviously, ReSharper can only accept the current code (templates).

So, in this case, check for null and do the “right thing”.


Consequence If the method in question was private, then ReSharper could analyze (although I'm not sure that it is) public code and make sure that there really is no way that this private method will be called using null , but since it is a public method and one available through interface then

ReSharper is wrong.

+7
source share

The documentation states that null values ​​should never be hashed, and that trying to do this should always throw an exception.

Of course, you can do whatever you want. If you want to create a hash-based structure for which null keys are valid, you can do this, in which case you should simply ignore this warning.

+3
source share

Here ReSharper has a special code. He will not warn about this ReferenceEquals:

 if (ReferenceEquals(obj, null)) { throw new ArgumentNullException("obj"); } 

He will warn about this ReferenceEquals:

 if (ReferenceEquals(obj, null)) { return 0; } 

Throwing an ArgumentNullException is consistent with the contract specified in IEqualityComparer (Of T). GetHashCode

If you go to the definition of IEqualityComparer (F12), you will also find additional documentation:

  // Exceptions: // System.ArgumentNullException: // The type of obj is a reference type and obj is null. int GetHashCode(T obj); 

So, ReSharper is right that something is wrong, but the error displayed does not correspond to the change you have to make to the code.

0
source share

All Articles