C# 对象相等性判断和同一性判断

C# 对象相等性判断和同一性判断

在日常开发中经常需要编写代码比较不同的对象。例如,有时需要将对象都放到一个集合中,并编写代码对集合中的对象进行排序、搜索或者比较。

System.Object类有两个Equals方法,如下:

1、实例Equals方法(可重写),代码如下:

public virtual bool equals(object obj) => RuntimeHelpers.Equals(this, obj)

再看看RuntimeHelpers.Equlas里面调的是什么方法,代码如下:

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public static extern bool Equals(object o1, object o2);

ok,这里的extern关键字告诉你,接下来的不用你考虑了!

2、静态方法Equals方法,代码如下:

public static bool Equals(object objA,object objB)=>
((objA==objB) || (((objA!=null) && (objB!=null)) &&  objA.Equals(objB)))

继续深入解析代码,发现objA.Equals调用了上面的实例Equals方法.其实就是在实例Equals方法的基础上做了非空判断.然后方法做了静态化.

到这里源码解析完毕,由于到extern这一步解析不下去了(博主实力有限),如有知道的请告知!万分感谢!

 

由于类型能够重写Equals方法,所以Equals方法的逻辑远比想象的要复杂.下面来举几个例子:

1、由于类型能够重写Equals方法,所以不能使用它来测试同一性,为了解决这个问题,Object类型提供了ReferenceEquals方法来比较两个对象的同一性,ReferenceEquals代码如下:

public static bool ReferenceEquals(object objA,object objB)=>(objA==objB)

注:判断两个对象的"同一性"不应该使用C#的==操作符(除非将两个操作符进行装箱转换为Object),因为某个操作数可能重载了==操作符

 

2、System.ValueType(所有值类型的基类)就重写了Object的Equals方法,并对两个对象进行了正确的值相等检查而不是同一性检查.代码如下:

public bool Equals(uint obj)=>(this == obj);

==操作符进行的值检查.

ValueType.Equals内部会进行一下操作:

1、如果obj实参为null,就返回false;

2、如果this和obj引用的是不同的对象,返回false;

3、针对类型定义的每个实例字段,都将this对象中的值与obj对象中的值进行比较(通过调用对象的Equals方法)。任何字段不相等,就返回false.

4、返回true,ValueType的Equals方法不掉用Object的Equals方法.

上述3步骤,是通过反射实现,由于CLR的反射机制效率不高,所以在定义自己的值类型的时候,应重写Equals方法来提供自己的实现,从而提高自己类型进行值类型比较时的性能.注:自己的实现不用调用base.Equals().

当我们定义自己的类型时,重写的Equals方法要符合下面几个特性:

1、Equals必须自反 x.Equals(x)肯定返回true.

2、Equlas必须对称 x.Equals(y)和y.Equals(x)必须返回相同的值

3、Equals必须可传递 x.Equals(y)返回true,y.Equals(z)返回true则x.Equals(z)也必须返回true.

4、Equals必须一致,比较的两个值不变,Equals返回值(true或false)也不能变

如果实现的Equals方法不符合上述特性,应用程序就会行为失常.

 

重写Equals方法必须做以下几件事

1、让类型实现System.IEquatable<T>接口的Equals方法

这个泛型接口允许定义类型安全的Equals方法,通常实现的Equals方法应获取一个Object参数,以便在内部调用类型安全的Equals方法.

2、重载==和!=操作符方法

通常应实现这些操作符方法,在内部调用类型安全的Equals方法.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值