咨询单字段与多字段类的HashCode重写规范及正确性
HashCode重写合规性分析
嘿,针对你提到的两种HashCode重写场景,我来逐一分析它们的合规性:
场景1:拥有三个及以上字段的对象
你给出的实现是完全合规的,而且是业界常用的经典写法:
public override int GetHashCode() { unchecked // Overflow is fine, just wrap { int hash = 17; // Suitable nullity checks etc, of course :) hash = hash * 23 + field1.GetHashCode(); hash = hash * 23 + field2.GetHashCode(); hash = hash * 23 + field3.GetHashCode(); return hash; } }
为什么合规?
- 17和23都是质数,质数作为乘数能有效减少不同对象哈希值碰撞的概率;
unchecked关键字允许整数溢出(溢出后自动循环),这在哈希计算里是可接受的,不会影响哈希的有效性;- 链式结合多个字段的哈希值,能确保对象的哈希值由所有参与相等判断的字段共同决定(前提是你Equals方法也用到了这些字段)。
小提醒:如果某个字段可能为null,一定要加空值判断,比如改成field1?.GetHashCode() ?? 0,避免抛出NullReferenceException。
场景2:仅拥有一个字段的对象
你提到的实现可以简化,直接返回该字段的哈希值就完全合规,没必要保留多余的复杂度:
public override int GetHashCode() { // 若field1可能为null,记得加空值处理 return field1?.GetHashCode() ?? 0; }
为什么不用复杂写法?
正如Zack指出的,单个字段的情况下,额外的17*23计算完全是冗余的——单个字段的哈希值已经能足够唯一地代表对象的标识,复杂写法既不会提升哈希质量,还会增加不必要的计算开销。只要你的Equals方法是基于这个字段判断相等的,这个简洁的实现就完全符合HashCode的契约(相等的对象必须有相同的哈希值,哈希值相同的对象不一定相等)。
内容的提问来源于stack exchange,提问作者w0051977
相关产品推荐
相关产品推荐

