关于实现等式操作符(==)的相关信息,请参考:[Equals 与等式操作符(==)的实现指南]。

  • 重载 GetHashCode 方法来允许类型在散列数据表中正确地运作。
  • 不要在 Equals 方法的实现中抛出异常。而是为 null 参量而返回 false。
  • 遵循 Object.Equals 方法中被定义的约定,如下所示:

    • x.Equals(x) 返回 true。
    • x.Equals(y) 与 y.Equals(x) 返回相同的值。
    • (x.Equals(y) && y.Equals(z)) 返回 true,如果 x.Equals(y) 或者 x.Equals(z) 的其中一个返回了 true,就直接返回 true。
    • 只要通过 x 与 y 被引用的对象没有被更改,对于 x.Equals(y) 的连续调用就会返回相同的值。
    • x.Equals(null) 返回 false。
  • 至于一些类别的对象,为值的相等而进行 Equals 测试来替代参考相等的做法是值得的。如果两个对象都有相同的值,那么就为 Equals 的实现而返回 true,即使它们不是相同的实例。对象值的组成定义等于类型的实现器,但是它通常是部分或者所有被存储在对象的实例变量中的数据。例如,一个基于字符串的值;String 类的 Equals 方法会为任何两个包含相同内容的字符串实例而返回 true 值。
  • 在一个基类的 Equals 方法中提供了相等的值的时候,派生类中的 Equals 方法重载就应该调用被继承的 Equals 实现。
  • 如果你使用了一种支持操作符重载的编程语言,并且你为一个被指定的类型而重载了等式操作符(==),那么这个类型就应该重载 Equals 方法。这种 Equals 方法的实现应该能够返回与等式操作符相同的结果。下列指南将有助于确保类库的代码中使用了 Equals(如 ArrayList 与 Hashtable)并且正确地运作在以等式操作符通过应用程序代码而被使用的一致风格中。
  • 如果你实现了一个值类型,那么你应该考虑重载 Equals 方法来获取在 ValueType 的默认 Equals 方法实现之上的被增强的性能。如果你重载了 Equals 以及编程语言所支持的操作符重载,那么你应该为你的值类型而重载等式操作符。
  • 如果你实现了引用类型,并且如果你的类型与基类型(如 Point、String、BigNumber,以及等等)一样,那么你应该考虑重载一个引用类型的 Equals 方法。大部分的引用类型都不应该重载等式操作符,即使它们已经重载了 Equals 方法。但是,如果你实现了一个被打算用来持有值语法的引用类型(如一个复合的数字类型),那么你就应该重载等式操作符。
  • 如果你为一个给定的类型实现了 IComparable 接口,你应该为那个类型而重载 Equals。

范例

下列代码范例示范了 Equals 方法的实现、重载调用,以及重载。

实现 Equals 方法

下列代码范例包含了对于默认 Equals 方法实现的两个调用。

Visual Basic
Imports System
Class SampleClass   Public Shared Sub Main()Dim obj1 As New System.Object()Dim obj2 As New System.Object()Console.WriteLine(obj1.Equals(obj2))obj1 = obj2Console.WriteLine(obj1.Equals(obj2))End Sub
End Class
C#
using System;
class SampleClass
{public static void Main() {Object obj1 = new Object();Object obj2 = new Object();Console.WriteLine(obj1.Equals(obj2));obj1 = obj2; Console.WriteLine(obj1.Equals(obj2)); }
}

前述代码的输出如下:

False
True
重载 Equals 方法

下列代码范例说明了重载 Equals 方法来提供值等式的一个 Point 类以及 Point 的派生类 Point3D。因为 Point 类的 Equals 重载是最先在继承链中被用来引入值等式的重载,所以基类(派生自 Object 并且检查参考等式)的 Equals 方法不会被调用。但是,Point3D.Equals 会调用 Point.Equals,因为 Point 是以提供值等式的风格来实现 Equals 的。

Visual Basic
Namespace Examples.DesignGuidelines.EqualsImplementationPublic Class Point  Protected x As IntegerProtected y As IntegerPublic Sub New (xValue As Integer, yValue As Integer)Me.x = xValueMe.y = yValueEnd SubPublic Overrides Overloads Function Equals(obj As Object) As BooleanIf obj Is Nothing OrElse Not Me.GetType() Is obj.GetType() ThenReturn FalseEnd IfDim p As Point = CType(obj, Point)Return Me.x = p.x And Me.y = p.yEnd Function Public Overrides Function GetHashCode() As IntegerReturn x Xor yEnd Function
End Class Public Class Point3DInherits PointPrivate z As IntegerPublic Sub New (xValue As Integer, yValue As Integer, zValue As Integer)MyBase.New(xValue, yValue)Me.z = zValueEnd SubPublic Overrides Overloads Function Equals(obj As Object) As BooleanReturn MyBase.Equals(obj) And z = CType(obj, Point3D).zEnd Function Public Overrides Function GetHashCode() As IntegerReturn MyBase.GetHashCode() Xor zEnd Function
End Class End Namespace
C#
using System;namespace Examples.DesignGuidelines.EqualsImplementation
{
class Point: object
{protected int x, y;public Point(int xValue, int yValue){x = xValue;y = yValue;}public override bool Equals(Object obj) {// 检查 null 值并且比较运行时类型。if (obj == null || GetType() != obj.GetType()) return false;Point p = (Point)obj;return (x == p.x) && (y == p.y);}public override int GetHashCode() {return x ^ y;}
}class Point3D: Point
{int z;public Point3D(int xValue, int yValue, int zValue) : base(xValue, yValue){z = zValue;}public override bool Equals(Object obj) {return base.Equals(obj) && z == ((Point3D)obj).z;}public override int GetHashCode() {return base.GetHashCode() ^ z;}
}
}

Point.Equals 方法检查到 obj 参量不是 null 值并且它还引用了与这个对象相同的一个类型实例。如果其中一种检查失败,方法返回 false 值。Equals 方法使用 GetType 方法来检查这两个对象的运行时类型是否完全相同。注意:typeof(在 Visual Basic 中是 TypeOf)在这里没有被使用,因为它返回静态的类型。如果方法已经被用来检查 obj 是否被替换成 Point,那么在 obj 是由 Point 所派生的一个实例的情况下,检查将会返回 true,尽管 obj 以及当前实例不是相同的运行时类型。已经被核实的那两个对象就是相同的类型,方法把 obj 转换成 Point 类型并且返回两个对象实例变量的对比结果。

在 Point3D.Equals 中,被继承的 Equals 方法在任何操作被完成之前被调用。被继承的 Equals 方法会核实那个 obj 不是 null、那个 obj 是与该对象一样的相同实例,并且被继承的实例变量相匹配。只在被继承的 Equals 返回 true 值的时候,方法才能够对比被引入到派生类中的实例变量。尤其是,对于 Point3D 的转换并没有被执行,除非已经检测到 obj 是 Point3D 类型或者是一个派生自 Point3D 的类。

使用 Equals 方法来对比实例变量

在前面的范例中,等式操作符(==)被用来对比单独的实例变量。在有些情况下,它适合于使用 Equals 方法在 Equals 的一个实现中对比实例变量,如下代码范例所示。

Visual Basic
Imports SystemClass RectanglePrivate a, b As PointPublic Overrides Overloads Function Equals(obj As [Object]) As BooleanIf obj Is Nothing Or Not Me.GetType() Is obj.GetType() ThenReturn FalseEnd IfDim r As Rectangle = CType(obj, Rectangle)' 使用 Equals 来对比实例变量。Return Me.a.Equals(r.a) And Me.b.Equals(r.b)End Function Public Overrides Function GetHashCode() As IntegerReturn a.GetHashCode() ^ b.GetHashCode()End Function
End Class
C#
using System;
class Rectangle
{Point a, b;public override bool Equals(Object obj) {if (obj == null || GetType() != obj.GetType()) return false;Rectangle r = (Rectangle)obj;// 使用 Equals 来对比实例变量。return a.Equals(r.a) && b.Equals(r.b);}public override int GetHashCode() {return a.GetHashCode() ^ b.GetHashCode();}
}
重载等式操作符(==)与 Equals 方法

在有些编程语言中(如 C#),操作符重载是被支持的。在一个类型重载了等式操作符(==)的时候,它应该同样重载 Equals 方法来提供相同的功能。这典型地通过在被重载的等式操作符(==)术语中编写 Equals 方法而被完成,如下代码范例所示。

C#
public struct Complex
{double re, im;public override bool Equals(Object obj) {return obj is Complex && this == (Complex)obj;}public override int GetHashCode() {return re.GetHashCode() ^ im.GetHashCode();}public static bool operator ==(Complex x, Complex y) {return x.re == y.re && x.im == y.im;}public static bool operator !=(Complex x, Complex y) {return !(x == y);}
}

因为 Complex 是一个 C# 结构(一个值类型),并且已知没有任何类将会从 Complex 那里被派生。因此,Equals 方法不需要对比每个对象的 GetType 结果。代替它的是使用 is 操作符来检查 obj 参数的类型。

转载于:https://www.cnblogs.com/Laeb/archive/2007/02/04/639594.html

.NET 指南:实现 Equals 方法相关推荐

  1. 为什么使用HashMap需要重写hashcode和equals方法_为什么要重写 hashcode 和 equals 方法?...

    1. 通过Hash算法来了解HashMap对象的高效性 2. 为什么要重写equals和hashCode方法 3. 对面试问题的说明 <Java 2019 超神之路> <Dubbo ...

  2. C# 重载 Equals() 方法、重载运算符、声明显隐式转换的简要整理

    自动生成 可以使用 JetBrains ReSharper 的代码生成功能来自动生成各种结构性的或可重载的成员,而不必自行手写,因为非常麻烦且易错. 如确需手写,可参考本文. 引用类型和值类型 本文不 ...

  3. JAVA-初步认识-第十一章-object类-equals方法覆盖

    一. 现在要谈论equals方法另一个方面.如果不写equals方法,直接用==来比较也是可以的,貌似equals方法有点多余. 现在不比较对象是否相等,而是比较对象中的特定内容,比如说对象的年龄,之 ...

  4. 【宋红康学习日记11】Object类与equals方法

    1 == (1)当对象是基本数据类型时,比较值: (2)当对象是引用型时,比较的是地址值!!1 2 equals():只处理引用型数据:Object类中的equals方法依然比较的是地址值! 但在St ...

  5. JAVA中重写equals()方法的同时要重写hashcode()方法

    object对象中的 public boolean equals(Object obj),对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true:注意:当此方法 ...

  6. Java基础学习总结(1)——equals方法

    2019独角兽企业重金招聘Python工程师标准>>> 一.equals方法介绍 1.1.通过下面的例子掌握equals的用法 1 package cn.galc.test; 2 3 ...

  7. Java培训教程:”==“和 equals 方法究竟有什么区别?

    在学习java技术过程中,我们会接触到一些变量值的相关知识,本期小编为大家介绍的教程就是关于"=="和 equals 方法究竟有什么区别?来看看下面的详细介绍. Java培训教程: ...

  8. 为什么阿里巴巴禁止使用BigDecimal的equals方法做等值比较?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! BigDecimal,相信对于很多人来说都不陌生,很多人都 ...

  9. 【Java常识】6.0面向对象认知和Eclipse的实用使用、==号和equals方法的区别

    1.曾经写过很多自以为很通俗易懂的面向对象的解释. 如下是目前最通俗的一种解释: 2.Eclipse的补充解释. 运行的快捷键:F11. 3.Eclipse快捷键大全 大全放本文最后,这里主要放常用的 ...

最新文章

  1. FusionChart
  2. mysql中鼠标光标消失了_为什么我这里没有显示鼠标的悬停可改变页面颜色,以为什么我加载了mysql的jar文件还是不能显示报表的内容呢?...
  3. Java 18 都要来了,你不会还在用Java 8吧?
  4. linux下nginx安装与设置开机启动
  5. Web服务(Apache、Nginx、Tomcat、Jetty)与应用(LAMP、CMS-WordPressGhost、Jenkins、Gitlab)
  6. CM: How is attachment version implemented
  7. try、catch、finally 和 throw-C#异常处理
  8. 如何高效管理我的时间?——时间会给你最好的答案
  9. 大数据、云计算、AI大牛都在这里了,就等你来捞干货
  10. 各操作系统各文件系统支持的最大文件的大小
  11. Linux系统管理(7)——Linux单用户模式详解 及应用场景
  12. 堡垒机应用发布服务器是干嘛的_支持Web UI数据库审计和敏感数据国密算法加密,JumpServer堡垒机v2.5.0发布丨Release Notes...
  13. js 自学,云知梦知识 点理论
  14. 神经网络与深度学习第3章:线性模型 阅读提问
  15. 数字相控阵雷达的优势(Benefits of Digital Phased Array Radars)1
  16. pythonnumpy安装教程_windows 下python+numpy安装实用教程
  17. 六(1) Python之列表
  18. 宿舍路由器设置傻瓜教程
  19. Linux下文件(文件夹)的压缩和解压
  20. error: unable to unlink old 'antzb-web/src/main/webapp/js/ny-details.js': Invalid argument

热门文章

  1. 解决pathForResource返回nil / 无法读取plist文件问题
  2. 安装ORACLE 11G R2 +redhat es4遇到的问题
  3. Android Context应用上下文详解
  4. CERT.RSA中证书的格式
  5. [转]个人开发者做一款Android App需要知道的事情
  6. SpringCloud微服务架构之,Hystrix 熔断器,Gateway 网关
  7. java中四种线程池及poolSize、corePoolSize、maximumPoolSize
  8. 搜狗浏览器,你开源了吗?
  9. golang导入包的几个说明:import
  10. Python的DEBUG LOG