zoukankan      html  css  js  c++  java
  • Equals() 和 运算符 == 重载准则 (C# 编程指南)

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

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

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

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

    重写 Equals

    Equals 是一个虚方法,允许任何类重写其实现。表示某个值(本质上可以是任何值类型)或一组值(如复数类)的任何类都应该重写 Equals。如果类型要实现 IComparable,则它应该重写 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 的任何类同时也重写 System.Object.GetHashCode。除了实现 Equals(对象)外,还建议所有的类为自己的类型实现 Equals(类型)以增强性能。例如:

     

    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 实现:

     

    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;
    }
    }

    Overriding Operator ==

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

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

     

    //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) 来检查引用相等性。这会导致调用重载的运算符 ==,从而导致无限循环。应使用 ReferenceEquals 或将类型强制转换为 Object 来避免无限循环。

    ------------------------------


    返回导读目录,阅读更多随笔



    分割线,以下为博客签名:

    软件臭虫情未了
    • 编码一分钟
    • 测试十年功


    随笔如有错误或不恰当之处、为希望不误导他人,望大侠们给予批评指正。

  • 相关阅读:
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结v2
    JS设置cookie、读取cookie、删除cookie
    Atitit 图像处理30大经典算法attilax总结
    Atitit数据库层次架构表与知识点 attilax 总结
    Atitit 游戏的通常流程 attilax 总结 基于cocos2d api
    Atitti css transition Animation differ区别
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结
    Atitit 全屏模式的cs桌面客户端软件gui h5解决方案 Kiosk模式
    Atitit 混合叠加俩张图片的处理 图像处理解决方案 javafx blend
    Atitit  rgb yuv  hsv HSL 模式和 HSV(HSB) 图像色彩空间的区别
  • 原文地址:https://www.cnblogs.com/08shiyan/p/1983257.html
Copyright © 2011-2022 走看看