GetHashCode()方法应该注意作为参数给出的空值吗?

本文关键字:参数 空值 方法 GetHashCode | 更新日期: 2023-09-27 18:08:33

在一些c#代码中,我使用linq GroupBy<TSource, TKey>()方法与自定义IEqualityComparer<T>

GroupBy(x => x.SomeField, new FooComparer());

我用作分组键的字段可以是null。因此,我不得不在Equals()方法中添加一些null检查:

public bool Equals(Foo x, Foo y)
{
    if (x == null && y == null)
       return true;
    else if (x == null && y != null)
       return false;
    else if (x != null && y == null)
       return false;
    else 
       return x.Id == y.Id;
}

问题是:我应该在GetHashCode()函数中做同样的事情吗?

public int GetHashCode(Foo obj)
{
    if (obj == null)          //is this really needed ?
       return default(int);   //
    else
       return obj.Id;
}

我不明白的东西:即使在GroupBy()方法中提供了空键,GetHashCode()也不会在obj参数中使用null对象调用。有人能告诉我为什么吗?(这只是"纯粹的机会",因为GroupBy()的实现方式和我给它的元素顺序?)


编辑:

正如caerolus所指出的,在GroupBy()的实现中有一些特殊的检查。

我检查了ILSpyGroupBy()是用Lookup<TKey, TElement>实现的

下面是相关的函数:

internal int InternalGetHashCode(TKey key)
{
    if (key != null)
    {
        return this.comparer.GetHashCode(key) & 2147483647;
    }
    return 0;
}

GetHashCode()方法应该注意作为参数给出的空值吗?

根据IEqualityComparer<T>.GetHashCode的文档:

ArgumentNullException
obj为引用类型,objnull

所以这是接口契约的一部分,因此你应该关心。如果objnull,通过抛出ArgumentNullException来实现。

你应该始终坚持一个接口,即使你怀疑或可以证明代码永远不会触及你不关心的部分。之后的更改可能会引入依赖于该行为的代码。