《Effective C#》:区别四个判等函数

.Net有四个判等函数?不少人看到这个标题,会对此感到怀疑。事实上确是 如此,.Net提供了ReferenceEquals、静态Equals,具体类型的Equals以及==操 作符这四个判等函数。但是这四个函数之间有细微的关系,改变其中一个函数的 实现会影响到其他函数的操作结果。

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

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

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

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

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

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

对于 第一个判等函数来说,没有什么好扩展的,因为本身已经很好地完成了它所要做 的。

对于第二个Object.Equals这个静态函数,其形式如下:

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

按照书中对它的分析,其大致函数代码如下:

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这个函数完成判等操作,需要经过三个步骤,第一步是需要根据 对象所属类型的==操作符的执行结果;第二步是判别是否为null,也是和第一步 一样,需要根据类型的==操作符的执行结果;最后一步要使用到类型的Equals函 数的执行结果。也就是说这个静态函数的返回结果,要取决于后面要提到的两个 判等函数。类型是否提供相应的判等函数,成为这个函数返回结果的重要因素。

那么对于Object.Equals这个静态方法来说,虽说接受参数的类型也属于 引用类型,但是不同于Object.ReferenceEquals函数,对于如下的代码,能得出 正确的结果。

int n = 10;
Debug.WriteLine( string.Format( "{0}", Object.Equals( n, n ) ) );
Debug.WriteLine( string.Format( "{0}", Object.Equals( n, 10 ) ) );

时间: 2024-08-29 06:13:55

《Effective C#》:区别四个判等函数的相关文章

递归函数(四):全函数与计算的可终止性

递归函数(一):开篇递归函数(二):编写递归函数的思路和技巧递归函数(三):归纳原理递归函数(四):全函数与计算的可终止性递归函数(五):递归集与递归可枚举集递归函数(六):最多有多少个程序递归函数(七):不动点算子递归函数(八):偏序结构递归函数(九):最小不动点定理 回顾 上文我们讨论了集合上的关系,还讨论了数学归纳法的一种普遍形式,称为良基归纳法, 它建立在集合上的良基关系之上. 本文开始讨论函数,我们将回顾函数的定义, 然后解释什么是全函数(total function),什么是部分函数

Sql Server函数全解<四>日期和时间函数

原文:Sql Server函数全解<四>日期和时间函数   日期和时间函数主要用来处理日期和时间值,本篇主要介绍各种日期和时间函数的功能和用法,一般的日期函数除了使用date类型的参数外,也可以使用datetime类型的参数,但会忽略这些值的时间部分.相同的,以time类型值为参数的函数,可以接受datetime类型的参数,但会忽略日期部分. 1.获取系统当前日期的函数getDate();  getDate()函数用于返回当前数据库系统的日期和时间,返回值的类型为datetime.[例]sel

JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是class对象 我们在上节验证了同步函数的锁是this,但是对于静态同步函数,你又知道多少呢? 我们做一个这样的小实验,我们给show方法加上static关键字去修饰 private static synchronized void show() { if (tick > 0) { try { Thread

IO端口和IO内存的区别及分别使用的函数接口

每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类.根据访问外设寄存器的不同方式,可以把CPU分成两大类.一类CPU(如M68K,Power PC等)把这些寄存器看作内存的一部分,寄存器参与内存统一编址,访问寄存器就通过访问一般的内存指令进行,所以,这种CPU没有专门用于设备I/O的指令.这就是所谓的"I/O内存"方式.另一类CPU(典型的如X86),将外设的寄存器看成一个独立的地址空间,所以访问内存的指令不能用来访问这

Linux Shell脚本系列教程(四):使用函数添加环境变量

  这篇文章主要介绍了Linux Shell脚本系列教程(四):使用函数添加环境变量,本文对环境变量的一知识作了介绍,并给出普通添加环境变量和使用函数添加环境变量的方法,需要的朋友可以参考下 一.简介 环境变量通常用于存储路径列表,这些路径用于搜索可执行文件.库文件等.例如:$PATH.$LD_LIBRARY_PATH,它们通常看起来像这样: 代码如下: PATH=/usr/bin;bin LD_LIBRARY_PATH=/usr/lib;lib 这意味着只要shell需要运行二进制可执行文件时

移动网站开发教程四,php自定义函数及数组

一.自定义函数 自定义函数就是我们自己定义的函数,在PHP中自定义函数格式如下: function funname(arg1, arg2, arg3......){ //TODO return values; }  代码如下 复制代码  <?php      function fun($m, $n){          if($m==0 || $n==0){              return 0;          }else{              $a=$m*$n;        

浅谈Excel开发(四) Excel自定义函数

相关文章: 浅谈Excel开发(1) Excel开发概述 浅谈Excel开发(二) Excel 菜单系统 浅谈Excel开发(三) Excel 对象模型 我们知道,Excel中有很多内置的函数,比如求和,求平均,字符串操作函数,金融函数等等.在有些 时候,结合业务要求,这些函数可能不能满足我们的需求,比如我想要一个函数能够从WebService上获取 某只股票的最新价:我想要一个函数能够获取当前的天气情况,这些需求我们可以通过编写Excel自定义 函数(User Define Function

JavaFX深入浅出(四)变量、函数

JavaFX的变量.函数与传统Java 语法相比,有一些不一样的地方. 一.变量和常量 1.声明 var 变量名 : 类型 = 变量值: def 常量名 : 类型 = 常量值: 其中,: 类型 是可选的,编译器会自动判断类型. var i:Integer = 12:var i1 = 11: //自动判断为 Integer def name:String = "hello":def name1 = "hello": //自动判断为 String def 声明的常量被赋

Effective C#原则35:选择重写函数而不是使用事件句柄

很多.Net类提供了两种不同的方法来控制一些系统的事件.那就是,要么添 加一个事件句柄:要么重写基类的虚函数.为什么要提供两个方法来完成同样的 事情呢?其实很简单,那就是因为不同的情况下要调用为的方法.在派生类的内 部,你应该总是重写虚函数.而对于你的用户,则应该限制他们只使用句柄来响 应一些不相关的对象上的事件. 例如你很了一个很不错的Windows应用程 序,它要响应鼠标点下的事件.在你的窗体类中,你可以选择重写OnMouseDown ()方法: public class MyForm :