重写Equals方法时为何要重写GetHashCode方法
重写Equals方法时为何要重写GetHashCode方法
技术背景
在.NET 中,当我们重写 Equals
方法时,通常也需要重写 GetHashCode
方法。这是因为.NET 的内置数据结构(如 Dictionary
、HashSet
等哈希集合)会使用 GetHashCode
方法返回的值来组织数据。如果不重写 GetHashCode
方法,可能会导致哈希集合在查找元素时出现不一致的行为。
实现步骤
1. 理解 Equals
和 GetHashCode
的关系
如果两个对象根据 Equals
方法判断为相等,那么它们的 GetHashCode
方法必须返回相同的值;但如果两个对象的 GetHashCode
方法返回相同的值,它们不一定相等,此时需要调用 Equals
方法进一步判断。
2. 重写 GetHashCode
方法
- 简单属性:如果对象只有一个关键属性,可以直接返回该属性的哈希码。
1 |
|
- 多个属性:当需要考虑多个属性时,可以使用一些算法将多个属性的哈希码组合起来。
1 |
|
- 使用
HashCode.Combine
(C# 8.0 及以后):这是一种更简洁的方式。
1 |
|
3. 重写 Equals
方法
重写 Equals
方法时,需要检查对象是否为 null
,并比较对象的类型和属性。
1 |
|
核心代码
简单属性的 GetHashCode
实现
1 |
|
多个属性的 GetHashCode
实现
1 |
|
使用 HashCode.Combine
的实现
1 |
|
最佳实践
- 保持一致性:确保
GetHashCode
方法使用的属性与Equals
方法一致。 - 避免使用可变属性:哈希码在对象的生命周期内应该保持不变,因此避免使用可以被外部修改的属性来计算哈希码。
- 考虑性能:选择合适的哈希码计算方法,以提高哈希集合的查找性能。
常见问题
不重写 GetHashCode
会怎样?
如果只重写了 Equals
方法而没有重写 GetHashCode
方法,可能会导致哈希集合(如 Dictionary
、HashSet
)在查找元素时出现问题。因为哈希集合会先比较对象的哈希码,如果哈希码不同,就不会调用 Equals
方法进行比较,从而可能导致相等的对象被认为不相等。
哈希码冲突怎么办?
哈希码冲突是不可避免的,因为可能的哈希码数量是有限的(int
类型为 2^32
)。一个好的哈希函数应该尽量均匀地分布哈希码,以减少冲突的概率。当发生冲突时,哈希集合会调用 Equals
方法进一步判断对象是否相等。
重写Equals方法时为何要重写GetHashCode方法
https://119291.xyz/posts/importance-of-overriding-gethashcode-when-equals-overridden/