博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Equals() 和运算符 == 的重写准则(C# 编程指南)
阅读量:6163 次
发布时间:2019-06-21

本文共 3539 字,大约阅读时间需要 11 分钟。

C# 中有两种不同的相等:引用相等和值相等。值相等是大家普遍理解的意义上的相等:它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。引用相等意味着要比较的不是两个对象,而是两个对象引用,且两者引用的是同一个对象。这可以通过简单的赋值来实现,如下面的示例所示:

C#
 
System.Object a = new System.Object();System.Object b = a;System.Object.ReferenceEquals(a, b);  //returns true

在上面的代码中,只存在一个对象,但存在对该对象的多个引用:a 和 b。由于它们引用的是同一个对象,因此具有引用相等性。如果两个对象具有引用相等性,则它们也具有值相等性,但是值相等性不能保证引用相等性。

若要检查引用相等性,应使用 。若要检查值相等性,请使用 。


由于  是一个虚方法,因此任何类都可以重写其实现。表示某个值(本质上可以是任何值类型)或一组值(如复数类)的任何类都应该重写Equals。如果类型要实现 ,则它应该重写 Equals

Equals 的新实现应该遵循  的所有保证:

  • x.Equals(x) 返回 true。

  • x.Equals(y) 与 y.Equals(x) 返回相同的值。

  • 如果 (x.Equals(y) && y.Equals(z)) 返回 true,则 x.Equals(z) 返回 true。

  • 只要不修改 x 和 y 所引用的对象,x.Equals(y) 的后续调用就返回相同的值。

  • x.Equals (null) 返回 false(仅非空值类型。有关更多信息,请参见。)

Equals 的新实现不应该引发异常。建议重写 Equals 的任何类同时也重写 。除了实现 Equals(对象)外,还建议所有的类为自己的类型实现 Equals(类型)以增强性能。例如:

C#
 
class TwoDPoint : System.Object{    public readonly int x, y;    public TwoDPoint(int x, int y)  //constructor    {        this.x = x;        this.y = y;    }    public override bool Equals(System.Object obj)    {        // If parameter is null return false.        if (obj == null)        {            return false;        }        // If parameter cannot be cast to Point return false.        TwoDPoint p = obj as TwoDPoint;        if ((System.Object)p == null)        {            return false;        }        // Return true if the fields match:        return (x == p.x) && (y == p.y);    }    public bool Equals(TwoDPoint p)    {        // If parameter is null return false:        if ((object)p == null)        {            return false;        }        // Return true if the fields match:        return (x == p.x) && (y == p.y);    }    public override int GetHashCode()    {        return x ^ y;    }}

可调用基类的 Equals 的任何派生类在完成其比较之前都应该这样做。在下面的示例中,Equals 调用基类 Equals,后者将检查空参数并将参数的类型与派生类的类型做比较。这样就把检查派生类中声明的新数据字段的任务留给了派生类中的 Equals 实现:

C#
 
class ThreeDPoint : TwoDPoint{    public readonly int z;    public ThreeDPoint(int x, int y, int z)        : base(x, y)    {        this.z = z;    }    public override bool Equals(System.Object obj)    {        // If parameter cannot be cast to ThreeDPoint return false:        ThreeDPoint p = obj as ThreeDPoint;        if ((object)p == null)        {            return false;        }        // Return true if the fields match:        return base.Equals(obj) && z == p.z;    }    public bool Equals(ThreeDPoint p)    {        // Return true if the fields match:        return base.Equals((TwoDPoint)p) && z == p.z;    }    public override int GetHashCode()    {        return base.GetHashCode() ^ z;    }}

默认情况下,运算符 == 通过判断两个引用是否指示同一对象来测试引用是否相等。因此引用类型不需要实现运算符 == 就能获得此功能。当类型不可变(即实例中包含的数据不可更改)时,通过重载运算符 == 来比较值是否相等而不是比较引用是否相等可能会很有用,因为作为不可变的对象,只要其值相同,就可以将其视为相同。建议不要在非不可变类型中重写运算符 ==

重载的运算符 == 实现不应引发异常。重载运算符 == 的任何类型还应重载运算符 !=。例如:

C#
 
//add this code to class ThreeDPoint as defined previously//public static bool operator ==(ThreeDPoint a, ThreeDPoint b){    // If both are null, or both are same instance, return true.    if (System.Object.ReferenceEquals(a, b))    {        return true;    }    // If one is null, but not both, return false.    if (((object)a == null) || ((object)b == null))    {        return false;    }    // Return true if the fields match:    return a.x == b.x && a.y == b.y && a.z == b.z;}public static bool operator !=(ThreeDPoint a, ThreeDPoint b){    return !(a == b);}
 说明:

运算符 == 的重载中的常见错误是使用 (a == b)(a == null) 或 (b == null) 来检查引用相等性。这会调用重载的运算符 ==,从而导致无限循环。应使用  或将类型强制转换为  来避免无限循环。


概念

参考

转载于:https://www.cnblogs.com/zhangchenliang/archive/2012/08/26/2657804.html

你可能感兴趣的文章
[转]Paul Adams:为社交设计
查看>>
showdialog弹出窗口刷新问题
查看>>
java
查看>>
Vue.js连接后台数据jsp页面  ̄▽ ̄
查看>>
关于程序的单元测试
查看>>
mysql内存优化
查看>>
都市求生日记第一篇
查看>>
Java集合---HashMap源码剖析
查看>>
SQL优化技巧
查看>>
thead 固定,tbody 超出滚动(附带改变滚动条样式)
查看>>
Dijkstra算法
查看>>
css 动画 和 响应式布局和兼容性
查看>>
csrf 跨站请求伪造相关以及django的中间件
查看>>
MySQL数据类型--与MySQL零距离接触2-11MySQL自动编号
查看>>
生日小助手源码运行的步骤
查看>>
Configuration python CGI in XAMPP in win-7
查看>>
bzoj 5006(洛谷 4547) [THUWC2017]Bipartite 随机二分图——期望DP
查看>>
CF 888E Maximum Subsequence——折半搜索
查看>>
欧几里德算法(辗转相除法)
查看>>
面试题1-----SVM和LR的异同
查看>>