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

详解“==”和equals的区别 详解“==”和equals的区别一、“==”二、equals()三、栗子和解释说明3.1栗子3.2基本数据类型的比较3.3引用数据类型的比较3.3.1String类3.3.2未重写equals方法的类四、练手栗子 “==”和equals 最大的区别是 “==”是运算符,如果是基本数据类型,则比较存储的值;如果是引用数据类型,则比较所指向对象的地址值。 equals是Object的方法,比较的是所指向的对象的地址值,一般情况下,重写之后比较的是对象的值。 一、“==” “==”是运算符 ①如果比较的对象是 阅读详情

.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 ) ) );

 

这是因为在此函数中要用到具体类型的两个判等函数,不过就函数本身而言,该做的判断都做了,因此不需要去重载添加复杂的操作。

 

为了更好的述说剩下两个函数,先解释一下等价的意义。对于等价的意义,就是自反、对称以及传递。

所谓自反,即a == a;

而对称,是a == b,则b == a;

传递是 a == b,b == c,则 a == c;

理解等价的意义后,那么在实现类型的判等函数也要满足这个等价规则。

 

对于可以重载的两个判等函数,首先来介绍的是类型的Equals函数,其大致形式如下:

public override bool Equals( object right );

 

那么对于一个类型的Equals要做些什么操作呢,一般来说大致如下:

    public class KeyData

    {

        private int nData;

        public int Data

        {

            get{ return nData;}

            set{ nData = value; }

        }

 

        public override bool Equals( object right )

        {

            //Check null

            if( right == null )

                return false;

 

            //check reference equality

            if( object.ReferenceEquals( this, right ) )

                return true;

 

            //check type

            if( this.GetType() != right.GetType() )

                return false;

 

            //convert to current type

            KeyData rightASKeyData = right as KeyData;

 

            //check members value

            return this.Data == rightASKeyData.Data;

        }

    }

 

如上增加了一个类型检查,即

if( this.GetType() != right.GetType() )

这部分,这是由于子类对象可以通过as转化成基类对象,从而造成不同类型对象可以进行判等操作,违反了等价关系。

 

除此外对于类型的Equals函数来,其实并没有限制类型非要属于引用类型,对于值类型也是可以重载此函数,但是我并不推荐,主要是Equals函数的参数类型是不可变的,也就是说通过此方法,值类型要经过装箱操作,而这是比较影响效率的。

 

而对于值类型来说,我推荐使用最后一种判等函数,即重载运算符==函数,其大致形式如下:

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函数。所以在编写自己类型的时候,要保留这种风格。

 

那么对于以上介绍的四种判等函数,会产生如下类似的对比表格。

 

操作结果取决于

适用范围

建议

Object.ReferenceEquals

两个参数对象是否属于同一个引用

引用类型

不要用它来判断值类型数据

Object.Equals

参数类型自身的判等函数

无限制

考虑装箱操作对值类型数据产生的影响

类型的Equals

类型重载函数

无限制

考虑装箱操作对值类型数据产生的影响

类型的==重载

类型重载函数

无限制

不要在引用类型中重载此运算符

 

那么在编写类型判等函数的时候,要注意些什么呢,给出如下几点建议。

首先,要判断当前定义的类型是否具有判等的意义;

其次,定义类型的判等函数要满足等价规则;

最后一点,值类型最好不要重载定义Equals函数,而引用类型最好不要重载定义==操作符。

 
Win10 IPv6 远程桌面连接(小米路由器) 背景 由于家里是移动网,且懒得向运营商要公网IPv4,所以想着用IPv6试一下。 家里的环境是这样的: 宽带用的是移动的,没有公网IPv4,但经过测试发现IPv6是公网的 上网通过光猫拨号,而不是通过路由器 路由器是小米AC2100 光猫更改为桥接模式 路由器必须要通过PPPoE拨号,如果是光猫拨号,那么要找对应的维护人员辅助你把光猫改成桥接模式。通过PPPoE拨号路由器就能够拿到公网的IPv6网段,也就可以给底下的其他服务分配公网IPv6了。而如果是光猫拨号,那么只有路由器可以拿到公网的IP。其他的设 阅读详情

相关推荐

4G LTE 与 5G 无线网络规划对比:从 BBU/RRU 到 CU/DU/AAU 的架构演进解析

本文深度解析4G LTE与5G无线网络架构的演进差异,从BBU/RRU分立式架构到CU/DU/AAU三级重构,揭示移动通信代际跃迁的技术本质。重点对比了网络规划中的覆盖能力、容量规划、传输网络等九大维度,为通信工程师提供实用的技术对照手册,助力5G网络高效部署。

weixin_32821533的博客 287

.net高级技术——关于相等(Equals)

1.我们使用Object的ReferenceEquals方法来判断两个实列是否时相同的对象 class Program { static void Main(string[] args) { Person p1 = new Person(); p1.Age = 12; p1....

qq_33407246的博客 747

避坑指南:在Ubuntu 22.04上配置UR5e与ROS2 Humble真机通信的完整流程

本文详细介绍了在Ubuntu 22.04上配置UR5e机械臂与ROS2 Humble真机通信的完整流程,包括环境准备、网络配置、URCap安装、ROS2驱动部署及控制器状态验证等关键步骤。特别针对常见问题如网络连接失败、驱动启动错误等提供了实用解决方案,帮助工程师高效完成UR5e与ROS2的集成工作。

weixin_30790841的博客 463

.NET类型对象的判等(Equals)

申明::本文内容来自>    .NET类型分为:基元类型(Primitive type),引用类型(Reference type),值类型(Value type),所有这些类型的祖先是System.Object,System.Object提供了四个成员函数:Equals GetHashCode GetType ToString ,以确保每个继承类型都有一个最小的操作集合,但是在我们设计.NET类型

Vigor's Blog 2731

inferCNV包安装问题及解决办法

InferCNV是一个由broad研究所开发的,利用单细胞转录组数据分析肿瘤细胞拷贝数变异(CNV)的工具。基本思路是在整个基因组范围内,通过计算肿瘤细胞关于参考的“正常”细胞的相对表达,利用滑窗思想对邻近的基因相对表达,计算拷贝数。 先贴一个官方安装说明: 官方infercnv安装说明 安装infercnv包: if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager") BiocManager:

m0_51042606的博客 6803

C/C++ 静态代码检查工具cppCheck

Cppcheck是一个用于C/C++代码的静态分析工具,它可以帮助开发者检测代码中的错误;Cppcheck可以检测出许多类型的错误,包括语法错误、未使用的函数、内存泄漏、未初始化的变量等;Cppcheck还支持用户自定义规则,这使得开发者可以根据自己的需求定制Cppcheck的行为;使用--suppress如果你想要忽略某些警告,可以在命令行中使用 --suppress 选项。

贝勒里恩的博客 4950

.NET 中 ==与Equals的区别

在C#中对于值类型的比较不管是用【==】还是【equals】都是对于其内容的比较,也就是说对于其值的比较,相等则返回true 不相等则返回false; 但是对于除string类型以外的引用类型 【==】比较的是在对象在栈上的引用是否相同而【equals】则比较的是对象在堆上的内容是否相同 示例代码: String str1 = new string('a',1); String str2 = new String('a',1);

W's play ground 610

1位2路选择器设计

1位2路选择器设计

好好学习,天天向上 3576

.net底层知识系列之三 比较 equals(静态、实例) referenceequals 深拷贝,浅拷贝

在C#中,有多种比较方法,有referenceequal,equals,equalsto,但他们之间是有细微差别的。referenceequal的实例class MyClass {   static void Main() {      object o = null;      object p = null;      object q = new Object();     

赛跑的专栏 2083

DOTS 性能基石:为什么传统 Unity 代码难以满足现代游戏需求?(DOTS 系列教程 · 第1篇)

本文探讨了Unity游戏开发中的性能优化问题,指出性能问题不应在最后才考虑,而应贯穿整个开发过程。文章分析了性能问题的三大表现(渲染开销、物理模拟、游戏逻辑),并解释了依赖硬件升级的不可行性。重点剖析了传统Unity代码性能低下的六大根源:垃圾回收卡顿、编译器优化不足、多核利用不足、数据结构和代码缓存不友好、过度抽象等问题。最后指出Unity项目中常见的反模式,如主线程垄断、内存碎片化等,为后续学习DOTS高性能架构解决方案奠定基础。

分享知识,拥抱变化 151

【ARM CoreLink 系列 3 -- CCI-550 控制器介绍 】

Arm CoreLink CCI-550 Cache Coherent Interconnect 扩展了 CoreLink CCI-500。它在 big.LITTLE 处理器集群之间提供完整的缓存一致性,并为其他代理(如 Mali GPU、网络接口或加速器)提供 I/O 一致性。CoreLink CCI-550 提供可扩展和可配置的互连,使 SoC 设计人员能够以尽可能小的面积和功耗满足性能目标,并且还增加了可降低整体系统延迟的监听滤波器。

CodingCos的博客 2210

[转载]《Effective C#》Item 9:区别和认识四个判等函数

《Effective C#》Item 9:区别和认识四个判等函数《Effective C#》Item 9:区别和认识四个判等函数 .Net有四个判等函数?不少人看到这个标题,会对此感到怀疑。事实上确是如此,.Net提...

congji3817的博客 115

Oracle EBS FA 创建成批增加执行时间长且报错

摘要 Oracle EBS系统在执行"创建成批增"请求时出现长时间运行并报错(ORA-00603和ORA-03114)。

陈显平的专栏-Oracle EBS 174

技术自媒体全平台变现:架构设计与自动化工具链实践

自媒体变现是通过内容创作实现价值转化的数字化模式,其核心原理在于精准的用户画像匹配和平台算法推荐机制。从技术视角看,高效变现需要构建系统化的内容架构和自动化工具链,这不仅能提升内容生产效率,还能实现知识资产的多重增值。在实际应用中,技术类自媒体凭借专业内容的长期价值和清晰的变现路径,特别适合采用Git版本控制、Markdown标准化写作和跨平台发布工具等技术方案。通过数据驱动的优化策略和合规运营机制,技术创作者能够在微信公众号、抖音、B站等主流平台建立可持续的变现体系,最终实现知识价值的最大化。

weixin_34284188的博客 321

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

转:《Effective C#》Item 9:区别和认识四个判等函数

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

flyskylf的专栏 529

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

《Effective+C#》Item+9:区别和认识四个判等函数(转载)

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

z4213489的专栏 703

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

More Effective C# Item9 :使用泛型元组代替out和ref参数

如果我们在进行设计时,需要针对一个方法返回多个结果,通常情况下,我们会使用ref或者out参数。同时,我们还是使用泛型元组来返回多个不相关的值。 我们来看下面的代码,首先定义一个具有继承关系的结构。 代码 1 publicclass Person 2 { 3 privatereadonlystring m_strName; 4 publicstring Name 5 ...

weixin_30498807的博客 79

Effective C# Item9:理解几个相等判断之间的关系

    C#中,有四种方式可以应用于“相等判断”,如下。 代码 public static bool ReferenceEquals( object left, object right ); public static bool Equals( object left, object right ); public virtual bool Equals( obj...

weixin_33912453的博客 131

C#学习资料《Effective C#》

Item 1: Always Use Properties Instead of Accessible Data Members《Effective C#》Item 1:用属性来访问类的私有成员http://blog.csdn.net/knight94/archive/2006/06/04/772886.aspxItem 2: Prefer readonly to const《Effectiv

SharpRose的专栏 1232
上一篇: 多线程断点续传研究之二
下一篇: 使用Double-Buffer来实现无闪烁动态折线图
Knight94
博客等级 码龄25年 1013粉丝 87原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值