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

首先来看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. Struts2 文件下载

    使用Struts2做一个简单的文件下载. 首先,导包,写配置文件就不说了. 进入主题. 文件下载操作类:FileDownload.java import java.io.InputStream; im ...

  2. javascript访问级别

    JavaScript中没有官方的访问级别语法,JavaScript没有类似于Java语言智能搞得private或protected这样的访问级别关键字,默认情况下,,对象中所有的成员都是公有和可访问的 ...

  3. 开VPN后能上网

    @echo ************************************************************************:start@echo off set /p ...

  4. symfony框架在中国移动cmwap网络下访问的问题

    最近用symfony框架给手机app做后台,发现在中国移动cmwap网络下会出现问题,所有请求都路由到根路径了 左图为原始$_SERVER对象,右图为$request->server对象由于re ...

  5. NVIDIA 显卡温度提示过高,显卡温度高99度怎么办?

    你可能没有在意您的NVIDIA(英伟达)显卡温度,那么你就不会知道显卡温度过高如何导致的呢?也不会知道如果去解决显卡温度过高的问题了,在此我希望在电脑玩游戏或者在办公中电脑速度快慢,或者发热的情况下, ...

  6. Altium Designer同一个工程里不同原理图导入到不同的PCB

    问题: 在用Altium Designer进行PCB工程设计时,有时一个工程里可能不止一块PCB,比如,一个设备里有主板和扩展板或者按键板等等,这时就需要在一个工程里添加多个PCB文件.如图: 我们知 ...

  7. C51 库函数

    C-51软件包的库包含标准的应用程序,每个函数都在相应的头文件(.h)中有原型声明.如果使用库函数,必须在源程序中用预编译指令定义与该函数相关的头文件(包含了该函数的原型声明).例如:#include ...

  8. rcp命令

    rcp命令 rcp代表“remote file copy”(远程文件拷贝).该命令用于在计算机之间拷贝文件.rcp命令有两种格式.第一种格式用于文件到文件的拷贝:第二种格式用于把文件或目录拷贝到另一个 ...

  9. cf500A New Year Transportation

    A. New Year Transportation time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  10. 基于HTML5 Canvas的饼状图表实现教程

    昨天我们分享了一款基于HTML5的线性图表应用,效果非常不错,可以看在线DEMO或者实现教程.今天我们继续来分享一款基于HTML5的网页图表,它也是利用Canvas绘制的,但是和前面不同的是,这款图表 ...