概要

  本方介绍.net如何判断两个对象是否相等

.Net有四个判等函数  

  1)Object.ReferenceEquals

  2)Object.Equals  

  3)对象实例的Equals

  4)==操作符

  这四个函数之间有细微的关系,改变其中一个函数的实现会影响到其他函数的操作结果。

Object.ReferenceEquals静态方法

  首先要说的是Object.ReferenceEquals和Object.Equals这两个静态函数,对于它们俩来说,是不需要进行重写的,因为它们已经完成它们所要得做的操作。

  对于Object.ReferenceEquals这个静态函数,函数形势如下:  

public static bool ReferenceEquals( object left, object right );

  这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后,就确定了它的使用范围,即只能对于引用类型操作。那么对于任何值类型数据操作,即使是与自身的判别,都会返回false。这主要因为在调用此函数的时候,值类型数据要进行装箱操作,分别装箱

int n = ;
Object.ReferenceEquals( n, n );

这是因为对于n这个数据装箱两次,而每次装箱后的地址有不同,而造成Object.ReferenceEquals( n, n )的结果永远为false

Object.Equals静态方法

  方法内部完成的工作:

public static void Equals( object left, object right )
{
// Check object identity
if( left == right )
return true; // both null references handled above
if( ( left == null ) || ( right == null ) )
return false; return left.Equals( right );
}

  也就是说,Object.Equals()判等需要3个步骤。

  第1步:对象所属类型的==操作符执行结果;

  第2 步:对象是否空引用(同第1步一样,使用对象所属类型的==操作符判断);

  第3步:对象所属类型的Equals()方法;

  因此,类型是否实现了自身的Equals()成为Object.Equals()返回什么结果的重要因素。

等价规则

  等价的意义就是自反、对称、传递。

  1)所谓自反,即:a==a;

  2)所谓对称:即:a==b; 则:b==a;

  3)所谓传递:即:a==b; b==c; 则: a==c;

  理解了等价的意义,那么实现或重写判等函数就要满足等价规则。

Equlas()可以重载的对象实例方法

public override bool Equals( object right );

自定义判等示例:

public override bool Equals( object right )
{
//step1:  Check null
if( right == null )
return false; //step2:  check reference equality
if( object.ReferenceEquals( this, right ) )
return true; //step3:  check type
if( this.GetType() != right.GetType() )
return false; //step4:  convert to current type for Equals
KeyData rightASKeyData = right as KeyData; //step5:  check members value
return this.Data == rightASKeyData.Data;
}

  如上代码增加了一个类型检查,即:if( this.GetType() != right.GetType() ),这部分,这是由于子类对象可以通过as转化成基类对象,从而造成不同类型对象可以进行判等操作,违反了等价关系。

==操作符,适用于值类型判等

public static bool operator == ( KeyData left,  KeyData right );

  一个值类型判等的实现示例:

public struct KeyData
{
  private int nData;
  public int Data
  {
    get{ return nData;}
    set{ nData = value; }
  }   public static bool operator == ( KeyData left, KeyData right )
  {
    return left.Data == right.Data;
  }   public static bool operator != ( KeyData left, KeyData right )
  {
    return left.Data != right.Data;
  }
}

  由于==操作与!=操作要同步定义,所以在定义==重载函数的时候,也要定义!=重载函数。这也是.Net在判等操作保持一致性的原则。

  那么对于最后一个判等函数,这种重载运算符的方法并不适合引用类型。这就是.Net一贯原则,去判断两个引用类型,不要用==,而要用某个对象的Equals函数。所以在编写自己类型的时候,要保留这种风格。

string引用类型的特殊性

  string是一个特殊的引用类型

  1)对象分配的特殊

string str1= "hello";
string str2= "hello;

  上面代码执行:

  .net为str1分配内存后,“hello"存储于内存堆中。

  .net为str2分配内存时会在名为“暂存表”的字符串集合中检查现有内存中已经分配过“hello"这个字符串,如果有,则将其引用分配给str2, 若无则分配新的内存空间。

  所以,上述代码执行后 str1、str2实际指向同一地址,即:Object.ReferenceEqulas(str1,str2)  //return true;

  2)对象引用操作的特殊

  例如:   

string str1 = "abcd";
string str2 = str1;
str2 = "efgh";// str1 is still "abcd" here

  当对于一个新的string类型是原有对象引用的时候,这点和一般的引用类型一样,但是当新的对象发生变化的时候,要重新分配一个新的地方,然后修改对象指向,上面代码执行str2="efgh",其引用不再指向str1,而是指向新分配内存引用。

  因此对于string操作的时候,尤其发生变化的时候,会显得比较慢,因为其牵扯到”暂存表“查找相同字符串、内存地址重新分配,所以对于数据量比较大的字符串操作时,使用StringBuilder成为最佳实践。

参考:

  http://blog.csdn.net/zhoufoxcn/article/details/1326904

区别和认识.net四个判等方法的更多相关文章

  1. 【转】区别和认识.Net四个判等函数

    原文地址:不详 .Net有四个判等函数?不少人看到这个标题,会对此感到怀疑.事实上确是如此,.Net提供了ReferenceEquals.静态Equals,具体类型的Equals以及==操作符这四个判 ...

  2. 《Effective C#》:区别和认识四个判等函数

    .Net有四个判等函数?不少人看到这个标题,会对此感到怀疑.事实上确是如此,.Net提供了ReferenceEquals.静态Equals,具体类型的Equals以及==操作符这四个判等函数.但是这四 ...

  3. String工具类之“四个判空方式”StringUtils.isNotBlank和StringUtils.isEmpty和StringUtils.isBlank和StringUtils.isNotEmpty

    一.判断str字符串都不为空==>StringUtils.isNotBlank(String str); 1 /** 2 * <p>检查一个字符串是否非空("") ...

  4. C#中四个判等函数的认识

    donet提供了四个判等函数,分别是referenceEqual,静态Equal,具体类型Equal,和==. 首先来说,object.referenceEqual和静态Equal public st ...

  5. iOS中常用的四种数据持久化方法简介

    iOS中常用的四种数据持久化方法简介 iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 ...

  6. JS用斜率判断鼠标进入DIV四个方向的方法 判断鼠标移入方向

    本文要介绍的是一种鼠标从一个元素移入移出时,获取鼠标移动方向的思路.这个方法可以帮助你判断鼠标在移入移出时,是从上下左右的哪个方向发生的.这个思路,是我自己琢磨出来,利用了一点曾经高中学过的数学知识, ...

  7. WordPress忘记密码找回登录密码的四种行之有效的方法

    WordPress忘记密码找回登录密码的四种行之有效的方法 PS:20170214更新,感谢SuperDoge同学提供的方法,登入phpMyAdmin后,先从左边选自己的数据库,然后点上面的 SQL ...

  8. Scrapy里Selectors 四种基础的方法

    在Scrapy里面,Selectors 有四种基础的方法xpath():返回一系列的selectors,每一个select表示一个xpath参数表达式选择的节点css():返回一系列的selector ...

  9. 运算符关键字。数据区别大小写。日期范围。判空的两种写法。NOT IN的两种写法。IN范围可含NULL,但NOT IN值范围不能含NULL。

    比较:>,<,=,>=,<=,<>(!=) 逻辑:AND,OR,NOT 范围:BETWEEN...AND... 范围:IN,NOT IN 判空:IS NULL, I ...

随机推荐

  1. idea2019.2激活码到2020.7.1【已失效】,有另外的

    ZKVVPH4MIO-eyJsaWNlbnNlSWQiOiJaS1ZWUEg0TUlPIiwibGljZW5zZWVOYW1lIjoi5o6I5p2D5Luj55CG5ZWGIGh0dHA6Ly9pZ ...

  2. 第6/7Beta冲刺

    1.团队成员 成员姓名 成员学号 秦裕航 201731062432(组长) 刘东 201731062227 张旭 201731062129 王伟 201731062214 2.SCRU部分 2.1各成 ...

  3. Oracle VM VirtualBox安装配置虚拟机Redhat7.6

    首先,准备好材料,需要下载Oracle VM VirtualBox.Oracle19C的安装包.Redhat7.6镜像 下面列出地址: Oracle VM VirtualBox安装包:链接:https ...

  4. Selenium自动化获取WebSocket信息

    性能日志 ChromeDriver支持性能日志记录,您可以从中获取域“时间轴”,“网络”和“页面”的事件,以及指定跟踪类别的跟踪数据. 启用性能日志 默认情况下不启用性能日志记录.因此,在创建新会话时 ...

  5. 【RocketMQ源码学习】- 4. Client 事务消息源码解析

    介绍 > 基于4.5.2版本的源码 1. RocketMQ是从4.3.0版本开始支持事务消息的. 2. RocketMQ的消息队列能够保证生产端,执行数据和发送MQ消息事务一致性,而消费端的事务 ...

  6. Python-09-文件处理

    一.文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 #1. 打开文件,得到文件句柄并赋值给一个变量 f=open('a.txt','r',encoding='u ...

  7. AVR单片机教程——拨动开关

    在按键的上方有4个拨动开关.开关与按键,在原理和使用方法上都是很类似的,但有不同的用途——按键按下后松开就会弹起,而开关可以保存其状态. <switch.h> 定义了与开关相关的函数.sw ...

  8. Python属性的查找顺序

    属性查找顺序 关于属性描述符请看上文>属性描述符   在梳理属性查找相关知识时,查看了很多的书籍和他人的博客,发现很多讲的过于抽象,并没有一个清晰的流程呈现.特此写下我对于此方面的理解和总结. ...

  9. mysql_select 单表查询

    select *         *代表全部   查询多个字段 select  字段1,字段2,字段3   聚合函数  count(*)       统计 select count(*)       ...

  10. C#程序结构(学习笔记01)

    C#程序结构 [原文参考官方教程] https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/program-structure C# ...