zoukankan      html  css  js  c++  java
  • 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方法.

  • 相关阅读:
    js拖动窗口 用层模拟可移动的小窗口
    tar命令详解
    linux内核编译过程的最终总结版
    用C#写ASP.NET搜索蜘蛛代码程序
    ID 为 333 的事件被添加到基于 Windows Server 2003 的计算机上的系统日志中的补丁下载地址
    简单实用的C#分词源代码(含词库素材下载)
    CSS截取固定长度字符串
    javascript 常用代码技巧大收集
    C# 特性(Attribute)
    关于iis HTTPERR日志
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/7481849.html
Copyright © 2011-2022 走看看