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()
的实现中有一些特殊的检查。
我检查了ILSpy
和GroupBy()
是用Lookup<TKey, TElement>
实现的
下面是相关的函数:
internal int InternalGetHashCode(TKey key)
{
if (key != null)
{
return this.comparer.GetHashCode(key) & 2147483647;
}
return 0;
}
根据IEqualityComparer<T>.GetHashCode
的文档:
ArgumentNullException
obj
为引用类型,obj
为null。
所以这是接口契约的一部分,因此你应该关心。如果obj
是null
,通过抛出ArgumentNullException
来实现。
你应该始终坚持一个接口,即使你怀疑或可以证明代码永远不会触及你不关心的部分。之后的更改可能会引入依赖于该行为的代码。