C#重写Equals()

之前讲过要重写Equals()就要重写GetHashCode(),这次说一下自己学到的如何重写Equals()。

首先,需要了解    “对象同一性”和“相等的对象”的含义区别

涉及到:相等的值类型、相等的引用类型、同一(相等的引用)

举个最简单的例子,一看便知:

 int  a=42;

int   b=42;

string aa="1";

string bb="1";

string cc=aa;

相信稍微懂点C#的因该知道,int为值类型,string为引用类型。

所以相等的值类型就是说a和b  ,,,相等引用类型为aa和bb,,,同一自然就是aa和cc

对象同一指两个引用假如引用同一个实例,即对象同一。可用ReferenceEquals()检查

两个对象实例也可能相等,如果标识它们的值相等,即相等的对象。

这里注意:::值类型本身不可能引用相等。!!

想一下ReferenceEquals()像参数传入同一个值类型,它们会复制到被调用的方法参数中,即装箱而每个实参装入了不同的箱中(即栈的不同位置),所以永远不可能引用相等。

下面说一下实现Equals():

重写步骤大体如下:

1.检查是否为null

2.如果是引用类型,则检查引用是否相等

3.检查数据类型是否相同

4.调用一个指定了具体类型的辅助方法,它能将操作数视为要比较的类型而不是一个对象

5.检查散列码是否相等,若不相等,必须继续执行全面的逐个字段比较

6.如果基类重写Equals,检查base.Equals();

7.比较每个标识字段,判断是否相等

8.重写GetHashCode

9.重写==和!=运算符

下面的例子进行展示

    public struct Longitude
    { }
    public struct Latitude { }
    public struct Coordinate
    {
        private readonly Latitude _Latitude;
        private readonly Longitude _Longitude;
        public Longitude Longitude
        {
            get { return _Longitude; }
        }
        public Latitude Latitude
        {
            get { return _Latitude; }
        }
        public Coordinate(Longitude longitude, Latitude latitude)
        {
            _Longitude = longitude;
            _Latitude = latitude;
        }

        public override bool Equals(object obj)
        {
            if (obj == null)//步骤1
                return false;
            if (this.GetType() != obj.GetType())//步骤3
                return false;
            return Equals((Coordinate)obj);//步骤4
            //return base.Equals(obj);
        }
        public bool Equals(Coordinate obj)//步骤4     比较两个Coordinate对象时,可以避开Equals(Object  obj)和GetType()检查
        {
            if (obj == null)//步骤1
                return false;
            if (ReferenceEquals(this, obj))//步骤2
                return true;
            if (this.GetHashCode() != obj.GetHashCode())//步骤5  效率低没有缓存,可以注释
                return false;
            System.Diagnostics.Debug.Assert(base.GetType() != typeof(object));
            //步骤6    基类没有重写可以注释
            if (!base.Equals(obj))
                return false;
            return ((Longitude.Equals(obj.Longitude)) && (Latitude.Equals(obj.Latitude)));//步骤7

        }
        /// <summary>
        /// //步骤9
        /// </summary>
        /// <param name="leftHandSide"></param>
        /// <param name="rightHandSide"></param>
        /// <returns></returns>

        public static bool operator ==(Coordinate leftHandSide, Coordinate rightHandSide)
        {
            if (ReferenceEquals(leftHandSide, null))
                return ReferenceEquals(rightHandSide, null);
            return (leftHandSide.Equals(rightHandSide));
        }
        public static bool operator !=(Coordinate leftHandSide, Coordinate rightHandSide)
        {
            return !(leftHandSide == rightHandSide);
        }
        /// <summary>
        /// //步骤8
        /// </summary>
        /// <returns></returns>

        public override int GetHashCode()
        {
            int hashCode = Longitude.GetHashCode();
            if (Longitude.GetHashCode() != Latitude.GetHashCode())
                hashCode ^= Latitude.GetHashCode();
            return hashCode;
            //return base.GetHashCode();
        }
    }

相等性实现基本原则:

1.Equals()、==、!=运算符应该一起实现

2.一个类型在Equals()、==、!=实现中应该使用相同算法

3.Equals()、==、!=实现时,也应实现一个类型的GetHashCode()

4.Equals()、==、!=、GetHashCode()永远不能引发异常

5.实现Icomparable时、与相等性有关的方法也应该实现

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值