In a generic GetHashCode(T foo)
method, I check whether foo
is null
.
However I just stumbled upon a strange Resharper warning.
In the following code, can foo
never be null
?
private class FooComparer<T> : IEqualityComparer<T> where T: Foo
{
public int GetHashCode(T foo)
{
// resharper warning: "Expression is always false"
if (Object.ReferenceEquals(null,foo)) return 0;
// ... calculate hash
}
}
However as far as I can tell, the following is perfectly legal:
Foo foo = null;
var fooComparer = new FooComparer<Foo>();
int hash = fooComparer.GetHashCode(foo);
Method IEqualityComparer<T>.GetHashCode
has contract [NotNull]
for its parameter because it has implementations that throw an exception when null
is provided as an argument.
If you want to use FooComparer<T>.GetHashCode
directly and exception-safe for null
as its argument, you can annotate it as follows:
public int GetHashCode([JetBrains.Annotations.CanBeNull] T foo)
{
// resharper warning: "Expression is always false"
if (Object.ReferenceEquals(null,foo)) return 0;
// ... calculate hash
}
Nevertheless analysis for [Not-Null]
-parameters must be improved. This bug exists for similar code in http://youtrack.jetbrains.com/issue/RSRP-304111
MSDN for IEqualityComparer<T>.GetHashCode Method
says:
Exceptions:
ArgumentNullException
The type of obj
is a reference type and obj
is null
.
This seems to imply that calling GetHashCode<T>(T obj)
with a null
parameter violates the contract of IEqualityComparer<T>
.
I assume Resharper assumes that callers adhere to that contract, and thus never pass in null
.