在 C# 中,类型的比较是如何实现的?在哪些情况下需要重写 Equals 和 GetHashCode 方法?请说明两者的关系。
考察说明
考察对 C# 中类型比较机制以及 Equals 和 GetHashCode 重写规范的理解。
回答思路
- 【回答框架 1】C# 中的类型比较主要分为引用相等和值相等。默认情况下,对于引用类型,== 和 Equals 都基于引用比较;对于值类型,默认的 Equals 基于值比较,但性能较低。可以通过重写 Equals 和 GetHashCode 以及运算符 == 和 != 来实现自定义的值相等比较。
- 【回答框架 2】重写 Equals 的场景包括:自定义值类型(如 struct)或需要值相等语义的类,例如实体类、值对象。重写时需保证自反性、对称性、传递性和一致性,并且与 GetHashCode 保持一致。
- 【回答框架 3】GetHashCode 用于在哈希表(如 Dictionary、HashSet)中快速定位,其必须与 Equals 保持一致:两个对象相等则哈希码必须相等。若未重写 GetHashCode,即使重写了 Equals,基于哈希的集合也可能出错。
- 【回答框架 4】普遍做法是使用模式匹配进行类型检查,结合字段比较实现 Equals,然后基于字段生成哈希码(如使用组合的 HashCode)。同时重载 == 和 !=,并考虑实现 IEquatable<T> 以避免装箱和便于泛型使用。
- 【关键点 1】默认引用类型比较为引用相等,值类型为值相等。
- 【关键点 2】重写 Equals 时必须同时重写 GetHashCode,且相等对象哈希码必须相等。
- 【关键点 3】重写 GetHashCode 时,如果相等性比较的字段不改变,应保证哈希码稳定。
- 【易错点 1】只重写 Equals 而不重写 GetHashCode,导致哈希集合行为异常。
- 【易错点 2】重写 GetHashCode 时,如果相等性比较的字段不改变,应保证哈希码稳定。
- 【易错点 3】在重写 == 时,如果参数为 null,需要注意类型检查,避免抛出异常。