你必须知道的.Net 8.2.2 本质分析
1 .Equals 静态方法
Equals 静态方法实现了对两个对象的相等性判别,其在 System.Object 类型中实现过程可以表 示为:
public static bool Equals(object objA, object objB)
{
if (objA == objB)
{
return true;
}
if ((objA != null) && (objB != null))
{
return objA.Equals(objB);
}
return false;
}
对以上过程,可以小结为:首先比较两个类型是否为同一实例,如果是则返回 true;否则将 进一步判断两个对象是否都为 null,如果是则返回 true;如果不是则返回 objA 对象的 Equals 虚方 法的执行结果。
所以,Equals 静态方法的执行结果,依次取决于三个条件:
l 是否为同一实例。
l 是否都为 null。
l 第一个参数的 Equals 实现。
因此,通常情况下 Equals 静态方法的执行结果常常受到判等对象的影响,例如有下面的测试 过程:
class Program5
{
public static void Main(string[] args)
{
MyClassA objA = new MyClassA();
MyClassB objB = new MyClassB();
Console.WriteLine(Equals(objA, objB));
Console.WriteLine(Equals(objB, objA));
Console.ReadKey();
}
}
class MyClassA
{
public override bool Equals(object obj)
{
return true;
}
}
class MyClassB
{
public override bool Equals(object obj)
{
return false;
}
}
//执行结果
True
False
由执行结果可知,静态 Equals 的执行取决于==操作符和 Equals 虚方法这两个因素。因此,决 议静态 Equals 方法的执行,就要在自定义类型中覆写 Equals 方法和重载==操作符。
还应注意到,.NET 提供了 Equals 静态方法可以解决两个值为 null 对象的判等问题,而使用 ob jA.Equals(object objB)来判断两个 null 对象会抛出 NullReferenceException 异常
public static void Main()
{
object o = null;
o.Equals(null);
}
2 .ReferenceEquals 静态方法
ReferenceEquals 方法为静态方法,因此不能在继承类中重写该方法,所以只能使用 System.Ob ject 的实现代码,具体为:
public static bool ReferenceEquals(object objA, object objB)
{
return (objA == objB);
}
可见,ReferenceEquals 方法用于判断两个引用是否指向同一个对象,也就是前文强调的引用 相等。因此以 ReferenceEquals 方法比较同一个类型的两个对象实例将返回 fasle,而.NET 认为 null 等于 null
因此,ReferenceEquals 方法,只能用于比较两个引用类型,而以 ReferenceEquals 方法比较值 类型,必然伴随着装箱操作的执行,分配在不同地址的两个装箱的实例对象,肯定返回 false 结果
从结果分析可知两次创建的 string 类型实例不仅内容相同,而且分享共同的内存空间,事实 上的确如此,这缘于 System.String 类型的字符串驻留机制,详细的讨论见 8.3 节“为什么特殊:str ing 类型解析”,在此我们必须明确 ReferenceEquals 判断引用相等的实质是不容置疑的。
3 .Equals 虚方法
Equals 虚方法用于比较两个类型实例是否相等,也就是判断两个对象是否具有相同的“值”, 在 System.Object 中其实现代码,可以表示为:
public virtual bool Equals(object obj)
{
return InternalEquals(this, obj);
}
其中 InternalEquals 为一个静态外部引用方法,其实现的操作可以表示成:
if (this == obj)
return true;
else
return false;
可见,默认情况下,Equals 方法和 ReferenceEquals 方法是一样的,Object 类中的 Equals 虚方 法仅仅提供了最简单的比较策略:如果两个引用指向同一个对象,则返回 true;否则将返回 false, 也就是判断是否引用相等。然而这种方法并未达到 Equals 比较两个对象值相等的目标,因此 Syste m.Object 将这个任务交给其派生类型去重新实现,可以说 Equals 的比较结果取决于类的创建者是 如何实现的,而非统一性约定。
事实上,.NET 框架类库中有很多的引用类型实现了 Equals 方法用于比较值相等,例如比较两 个 System.String 类型对象是否相等,肯定关注其内容是否相等,判断的是值相等语义:
4 .== 操作 符
在.NET 中,默认情况下,操作符“==”在值类型情况下表示是否值相等,由值类型的根类 Syste m.ValueType 提供了实现;而在引用类型情况下表示是否引用相等,而“!=”操作符与“==”语义类似。 当然也有例外,System.String 类型则以“==”来处理值相等。因此,对于自定义值类型,如果重载 E quals 方法,则应该保持和“==”在语义上的一致,以返回值相等结果;而对于引用类型,如果以覆 写来处理值相等规则时,则不应该再重载“==”运行符号,因为保持其缺省语义为判断引用相等才 是恰当的处理规则。
Equals 虚方法与==操作符的主要区别在于多态表现:Equals 通过虚方法覆写来实现,而==操 作符则是通过运算符重载来实现,覆写和重载的区别请参考 1.4 节“多态的艺术”。
你必须知道的.Net 8.2.2 本质分析的更多相关文章
- C#刨根究底:《你必须知道的.NET》读书笔记系列
一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...
- (转)【推荐】初级.NET程序员,你必须知道的EF知识和经验
转自:http://www.cnblogs.com/zhaopei/p/5721789.html [推荐]初级.NET程序员,你必须知道的EF知识和经验 阅读目录 [本文已下咒.先顶后看,会涨 ...
- 《你必须知道的.NET》读书笔记一:小OO有大智慧
此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.对象 (1)出生:系统首先会在内存中分配一定的存储空间,然后初始化其附加成员,调用构造函数执行初 ...
- 《你必须知道的.NET》读书笔记二:小OO有大原则
此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.单一职责原则 (1)核心思想:一个类最好只做一件事,只有一个引起它变化的原因 (2)常用模式:Fa ...
- 《你必须知道的.NET》读书笔记三:体验OO之美
此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.依赖也是哲学 (1)本质诠释:“不要调用我们,我们会调用你” (2)依赖和耦合: ①无依赖,无耦合 ...
- 《你必须知道的.NET》读书笔记:从Hello World认识IL
通用的语言基础是.NET运行的基础,当我们对程序运行的结果有异议的时候,如何透过本质看表面,需要我们从底层来入手探索,这时候,IL便是我们必须知道的基础. 一.IL基础概念 1.1 什么是IL? IL ...
- MVC中你必须知道的13个扩展点
MVC中你必须知道的13个扩展点 pasting 转:http://www.cnblogs.com/kirinboy/archive/2009/06/01/13-asp-net-mvc-extensi ...
- 前端开发必须知道的JS(二) 闭包及应用
http://www.cnblogs.com/ljchow/archive/2010/07/06/1768749.html 在前端开发必须知道的JS(一) 原型和继承一文中说过下面写篇闭包,加之最近越 ...
- 《你必须知道的.NET》书中对OCP(开放封闭)原则的阐述
开放封闭原则(OCP,Open Closed Principle)是面向对象原则的核心.由于软件设计本身所追求的墓边就是封装变化,降低耦合,而开放封闭原则就是对这一目标的直接体现.(你必须知道的.NE ...
随机推荐
- OPENTSDB: Request failed: Internal Server Error net.opentsdb.core.IllegalDataException
今天Opentsdb补传历史数据的时候,出现了如下的错误: Request failed: Internal Server Error net.opentsdb.core.IllegalDataExc ...
- 「NOI2006」最大获利
「NOI2006」最大获利 传送门 最小割. 对于每一组用户群 \(A_i, B_i, C_i\) ,连边 $S \to A_i, S \to B_i, $ 容量为成本,还有 \(i \to T\) ...
- Python 爬取 热词并进行分类数据分析-[云图制作+数据导入]
日期:2020.01.28 博客期:136 星期二 [本博客的代码如若要使用,请在下方评论区留言,之后再用(就是跟我说一声)] 所有相关跳转: a.[简单准备] b.[云图制作+数据导入](本期博客) ...
- Python回收机制
1.小整数对象池 整数在程序中的使用非常广泛,python 为了优化速度,使用了小整数对象池,避免整数频繁申请和销毁和内存空间. Python 对小整数的定义事[-5, 257]这些整数对象的hi提前 ...
- pycharm中Terminal中运行用例
1.设置终端路径 2.单个用例文件运行 3.多个用例文件,例如加载用例的文件运行 1.可能会出现如下错误(参考:https://blog.csdn.net/qq_36829091/article/d ...
- spring boot 中容器 Jetty、Tomcat、Undertow
spring boot 中依赖tomcat <dependency> <groupId>org.springframework.boot</groupId> < ...
- Java基础 -2.6
String字符串 在任何语言里面 都没有提供所谓的字符串这种基本数据类型,但是从实际的使用上来讲呢,各个编程语言 为了方便程序的开发,也都会提供有字符串的相应描述 在进行字符串变量使用的时候也可以使 ...
- Duilib程序添加托盘图标显示
转载:https://www.zhaokeli.com/article/8266.html 温馨提示:技术类文章有它的时效性,请留意文章更新时间以及软件的版本 功能描述 实现点击关闭后,程序最小化到托 ...
- 【PAT甲级】1013 Battle Over Cities (25 分)(并查集,简单联通图)
题意: 输入三个整数N,M,K(N<=1000,第四个数据1e5<=M<=1e6).有1~N个城市,M条高速公路,K次询问,每次询问输入一个被敌军占领的城市,所有和该城市相连的高速公 ...
- 31 反射方式给类的属性赋值 和 对象赋值(clone)
1.配置类 package com.da.tool.util.configuration.reflect; /** */ public class JobInfo { private String j ...