对象相等比较机制对于引用类型的变量和值类型的变量来说是不同的,下面分别介绍引用类型和值类型的相等比较.

首先来看System.Object的部分定义:

    public class Object
{
// 摘要:
// 确定指定的 System.Object 是否等于当前的 System.Object。
// 参数:
// obj:与当前的 System.Object 进行比较的 System.Object。
// 返回结果:
// 如果指定的 System.Object 等于当前的 System.Object,则为 true;否则为 false。
public virtual bool Equals(object obj);
//
// 摘要:
// 确定指定的 System.Object 实例是否被视为相等。
// 参数:
// objB:要比较的第二个 System.Object。
// objA:要比较的第一个 System.Object。
// 返回结果:
// 如果 objA 是与 objB 相同的实例,或者如果两者均为空引用,或者如果 objA.Equals(objB) 返回 true,则为 true;否则为
// false。
public static bool Equals(object objA, object objB);
//
// 摘要:
// 确定指定的 System.Object 实例是否是相同的实例。
// 参数:
// objB:要比较的第二个 System.Object。
// objA:要比较的第一个 System.Object。
// 返回结果:
// 如果 objA 是与 objB 相同的实例,或者如果二者都为空引用,则为 true;否则为 false。
public static bool ReferenceEquals(object objA, object objB);
}
}

System.Object中定义了三个比较是否相等的方法.还有一个运算符(==),这个运算符可以比较引用,也可以比较值.

下面来详细的介绍这四个方法:


1。引用类型的相等比较

方法1:public static bool ReferenceEquals(object objA, object objB);

描述:ReferenceEquals()是个静态方法,测试两个引用是否指向类的同一个实例,即两个变量中存的地址是否是同一个地址.

例子:

public partial class Equals_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SomeClass sc1 = new SomeClass();
SomeClass sc2 = new SomeClass();
//输出false
Response.Write(ReferenceEquals(sc1, sc2) + "<br/>");
//输出false
Response.Write(ReferenceEquals(sc1, null) + "<br/>");
//输出false
Response.Write(ReferenceEquals(null, sc1) + "<br/>");
//输出true
Response.Write(ReferenceEquals(null, null) + "<br/>");
}
} public class SomeClass
{ }

方法2:public virtual bool Equals(object obj);

描述:这个方法也比较引用,但因为该方法是虚拟的,所以可以在自己的类中重写它,按值来比较对象.

例子:

public partial class Equals_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SomeClass sc1 = new SomeClass(10);
SomeClass sc2 = new SomeClass(11);
//输出false
Response.Write(sc1.Equals(sc2) + "<br/>");
//输出false
Response.Write(sc1.Equals(null) + "<br/>");
//输出true
Response.Write(sc1.Equals(sc1) + "<br/>");
}
} public class SomeClass
{
private int _age; public SomeClass(int age)
{
this._age = age;
} public override bool Equals(object obj)
{
SomeClass sc = obj as SomeClass;
if (sc == null)
{
return false;
} return this._age == sc._age;
}
}

方法3:public static bool Equals(object objA, object objB);

描述:Equals的静态版本与其虚拟实例版本的作用相同,其区别是静态版本带有两个参数.并对它们进行比较.这个方法可以处理两个对象中有一个是null的情况,因此,如果有一个对象为null,则会抛出异常.

注意:如果两个对象都为null,则返回true.

   如果仅有一个对象为null,返回false.

   如果两个对象都不为null,则会调用抽象的Equals方法.

这表明,如果是比较两个对象,重写了虚拟的Equals方法,相当于重写了静态的Equals方法.

例子:

public partial class Equals_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SomeClass sc1 = new SomeClass(10);
SomeClass sc2 = new SomeClass(11);
//输出true
Response.Write(object.Equals(null, null) + "<br/>");
//输出false
Response.Write(object.Equals(sc1, null) + "<br/>");
//输出false
Response.Write(object.Equals(sc1, sc2) + "<br/>");
}
} public class SomeClass
{
private int _age; public SomeClass(int age)
{
this._age = age;
} public override bool Equals(object obj)
{
SomeClass sc = obj as SomeClass;
return this._age == sc._age;
}
}
比较运算符:==
描述:这个运算符介于严格的值比较和严格的引用比较之间.
例子:
public partial class Equals_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SomeClass sc1 = new SomeClass();
SomeClass sc2 = new SomeClass();
//输出false
Response.Write(sc1 == sc2);
}
} public class SomeClass
{ }

2。值类型

在进行值比较时,ReferenceEquals仍然用于比较引用,如下例:

public partial class Equals_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//输出false
Response.Write(ReferenceEquals(1,1));
}
}

输出false的原因是ReferenceEquals比较的引用,对于两个值类型的1和1,分别执行了装箱操作,导致两个参数实际上是不同的引用.

在进行值比较时Microsoft在System.ValueType类中已经重载了实例方法Equals,所以:

Equals比较的就是值:

public partial class Equals_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
int i = 1;
//输出true
Response.Write(i.Equals(1));
}
}

对于静态的Equals来说.实际调用的是虚拟的Equals方法.

public partial class Equals_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//输出true
Response.Write(object.Equals(1,1));
}
}

小结:

ReferenceEquals使用比较的是引用,若两个实例指向同一个对象,则返回true,否则返回false.

静态的Equals方法在比较非空对象和值时主要调用虚拟的Equals方法.主要看虚拟的Equals方法在被重写时是如何写的.

C#--对象的相等比较的更多相关文章

  1. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  2. javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈

    Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...

  3. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  4. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

  5. JS核心系列:浅谈原型对象和原型链

    在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象(Object)和函数对象(Function). 一般而言,通过new Function产生的对象是函数对象,其他对 ...

  6. Chrome出了个小bug:论如何在Chrome下劫持原生只读对象

    Chrome出了个小bug:论如何在Chrome下劫持原生只读对象 概述 众所周知,虽然JavaScript是个很灵活的语言,浏览器里很多原生的方法都可以随意覆盖或者重写,比如alert.但是为了保证 ...

  7. XStream将java对象转换为xml时,对象字段中的下划线“_”,转换后变成了两个的解决办法

            在前几天的一个项目中,由于数据库字段的命名原因 其中有两项:一项叫做"市场价格"一项叫做"商店价格" 为了便于区分,遂分别将其命名为market ...

  8. ASP.NET内置对象的总结

    1. Response对象可形象的称之为响应对象,用于将数据从服务器发送回浏览器. 实例源码:链接: http://pan.baidu.com/s/1dDCKQ8x 密码: ihq0  2. Requ ...

  9. ADO.NET对象的详解

    1. Connection 类 和数据库交互,必须连接它.连接帮助指明数据库服务器.数据库名字.用户名.密码,和连接数据库所需要的其它参数.Connection对象会被Command对象使用,这样就能 ...

  10. 对Castle Windsor的Resolve方法的解析时new对象的探讨

    依赖注入框架Castle Windsor从容器里解析一个实例时(也就是调用Resolve方法),是通过调用待解析对象的构造函数new一个对象并返回,那么问题是:它是调用哪个构造函数呢? 无参的构造函数 ...

随机推荐

  1. 找不到请求的 .Net Framework Data Provider。可能没有安装。

    解决方法: 安装Microsoft SQL Server Compact 4.0. 安装Microsoft SQL Server Compact 4.0之后,程序运行正常. 问题的原因就是程序连接.s ...

  2. MongoDB insert/update/one2many案例

    以博文与评论为例,博文有标题内容,对应多个评论,评论有评论人.评论内容等. ()插入一条博文: db.blog.insert( {','title':'this is blog title1','co ...

  3. P0口上拉电阻选择

    如果是驱动led,那么用1K左右的就行了.如果希望亮度大一些,电阻可减小,最小不要小于200欧姆,否则电流太大:如果希望亮度小一些,电阻可增大,增加到多少呢,主要看亮度情况,以亮度合适为准,一般来说超 ...

  4. nginx入门配置

    user www www; worker_processes 4; error_log logs/error.log; #pid logs/nginx.pid; events { worker_con ...

  5. ~/.bashrc的常用alias设置

    centos6.5系统中,alias定义在/etc/bashrc,分别写在/etc/profile.d/*.sh中,可以在此目录添加my.sh, alias attrib='chmod'alias c ...

  6. kill,killall,top,free,vmstat,iostat,watch命令

    kill命令 Linux 中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令.通常,终止一个前台进程可以 使用Ctrl+C键,但是,对 ...

  7. ortp使用详解2

    五:数据的接收和发送 1. 发送过程: 应用发送数据时调用接口 rtp_session_send_with_ts 完成.参数为会话句柄,数据缓冲区地址,数据长度以及应用当前的时间戳.在该接口中,会先调 ...

  8. 5s

    整理,整顿,清楚,清洁,身美

  9. android 利用反射机制获取drawable中所有的图片资源

    public List<Map<String,Object>> getGridData() { list=new ArrayList<Map<String,Obje ...

  10. Javascript:阻止浏览器默认右键事件,并显示定制内容

    在逛一些知名图片社区的时候,遇到自己心怡的图片,想要右键另存的时候,默认的浏览器菜单不见了,却出现了如:[©kevin版权所有]之类的信息: 今天在看Javascript事件默认行为相关的知识,所以, ...