ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Equals() 和运算符 == 的重写准则(C# 编程指南)

2021-12-27 14:33:27  阅读:133  来源: 互联网

标签:return C# Object Equals 运算符 obj public


1.概述

C# 中有两种不同的相等:引用相等和值相等。

值相等:是大家普遍理解的意义上的相等:它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。

引用相等:意味着要比较的不是两个对象,而是两个对象引用,且两者引用的是同一个对象。这可以通过简单的赋值来实现,如下面的示例所示:

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

在上面的代码中,只存在一个对象,但存在对该对象的多个引用:a 和 b。

由于它们引用的是同一个对象,因此具有引用相等性。如果两个对象具有引用相等性,则它们也具有值相等性,但是值相等性不能保证引用相等性。

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

2.Equals

这个Equals一般指的是Object.Equals(obj)

2.1源代码中的Equals

///object的equals
public virtual bool Equals(Object obj)
{
    return RuntimeHelpers.Equals(this, obj);
}

///RuntimeHelpers.Equals
[System.Security.SecuritySafeCritical]  // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public new static extern bool Equals(Object o1, Object o2);

2.2 ValueType中的Equals方法

​ ValueType中的Equals方法重写了object的equals方法。

2.3 关于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(仅非空值类型。有关更多信息,请参见可空类型(C# 编程指南)。)

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

class Point
{
  internal int x;
  internal int y;

  public Point(int X, int Y)
  {
     this.x = X;
     this.y = Y;
  }

  public override bool Equals (Object obj)
  {
     // Performs an equality check on two points (integer pairs).
     if (obj == null || GetType() != obj.GetType()) return false;
     Point p = (Point)obj;
     return (x == p.x) && (y == p.y);
  }

  public override int GetHashCode()
  {
     return Tuple.Create(x, y).GetHashCode();
  }
}

3. 重写运算符 ==

目的:通过重载运算符 == 来比较值是否相等。

默认情况下,运算符 == 通过判断两个引用是否指示同一对象来测试引用是否相等。

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

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

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

4.项目中代码编写

public class UserProperty
{
    int? _requestHashCode;
    /// <summary>
    /// 用户ID
    /// </summary>
    public int AppUserId { get; set; }
    /// <summary>
    /// key
    /// </summary>
    public string Key { get; set; }
    /// <summary>
    /// 文本
    /// </summary>
    public string Text { get; set; }
    /// <summary>
    /// 值
    /// </summary>
    public string Value { get; set; }

    public override int GetHashCode()
    {
        if (!IsTransient())
        {
            if (!_requestHashCode.HasValue)
                _requestHashCode = (this.Key + this.Value).GetHashCode();
            return _requestHashCode.Value;
        }
        return base.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        if (obj == null || !(obj is UserProperty))
            return false;
        if (Object.ReferenceEquals(this, obj))
            return true;
        UserProperty item = (UserProperty)obj;
        if (item.IsTransient() || this.IsTransient())
            return false;
        else
            return item.Key == this.Key && item.Value == this.Value;
    }


    public bool IsTransient()
    {
        return string.IsNullOrEmpty(this.Key) || string.IsNullOrEmpty(this.Value);
    }

    public static bool operator ==(UserProperty left, UserProperty right)
    {
        if (Object.Equals(left, null))
        {
            return (Object.Equals(right, null)) ? true : false;
        }
        else
        {
            return left.Equals(right);
        }
    }

    public static bool operator !=(UserProperty left, UserProperty right)
    {
        return !(left == right);
    }
}

参考资料

Equals() 和运算符 == 的重写准则(C# 编程指南)

C#源代码

标签:return,C#,Object,Equals,运算符,obj,public
来源: https://www.cnblogs.com/ccmonsor/p/15736123.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有