C#中==(双等于号)与equals()区别详解
作者:陈大宝 发布时间:2021-09-21 18:49:42
这两种方式也是大家在日常编码工作当中用的比较多的判断方式、之前在使用的时候也没太关注两者在比较不同类型的时候存在哪些区别
今天就和大家一起深入了解一下其中区别
一、值类型比较判断
对于值类型来说 两者之间比较的都是”内容”是否相同,即值类型中的数值是否一样,很显然此时两者是划等号的,代码展示如下:
#region 值类型判断
int i = 10;
int j = 10;
Console.WriteLine($"双等于号判断结果为:{(i == j)}");
Console.WriteLine($"Equals判断结果为:{i.Equals(j)}");
#endregion
控制台输出:
由此判断在值类型中使用int类型为例,其中等于号与Equals二者的判断不存在区别、都是比较其中的数值内容、那么引用类型存在区别吗一起来看一看?
二、引用类型比较判断
对于引用类型来说,等号(==)比较的是两个变量的”引用”是否一样,即是引用的”地址”是否相同。而对于equals来说仍然比较的是变量的”内容”是否一样
1、引用类型中字符串比较(String)
#region 引用类型中String比较
Console.WriteLine("----------------我是分割线-----------------------");
string str1 = "abd";
string str2 = "abd";
Console.WriteLine($"双等于号判断结果为:{(str1 == str2)}");
Console.WriteLine($"Equals判断结果为:{str1.Equals(str2)}");
#endregion
控制台输出:
那么问题来了?Equals是比较其中的数值相等返回True我可以理解、那么字符串中双等于号是比较二者之间的引用、很显然str1变量与str2变量是不同的引用
为什么返回的结果怎么还是True呢?实际的原因是什么呢?一起来看一看
//
// 摘要:
// Determines whether two specified strings have the same value.
//
// 参数:
// a:
// The first string to compare, or null.
//
// b:
// The second string to compare, or null.
//
// 返回结果:
// true if the value of a is the same as the value of b; otherwise, false.
public static bool operator ==(String? a, String? b);
//
// 摘要:
// Determines whether this instance and another specified System.String object have
// the same value.
//
// 参数:
// value:
// The string to compare to this instance.
//
// 返回结果:
// true if the value of the value parameter is the same as the value of this instance;
// otherwise, false. If value is null, the method returns false.
public bool Equals(String? value);
不管是==、还是Equals也好都是微软提供的public sealed class String密封类下面的提供的方法、看到此时还看不出其中的缘由、那么直接上反编译工具看一看究竟。
点击str3==str2中的等于号继续查看、发现反编译中查看这个方法的源码返回了Equals这个方法、这样一看就大致清楚了、string类型中微软的开发
人员对这个==进行的重写。
以上是Equals与==反编译源码所以这也就是当我们在比较String类型时、不同的引用、数值一样、Equals与==返回的结果一致、相同、所以在进行String类型判断
这两个方法内部本质是相同的、当然String类型是一个特例。
2、引用类型中自定义类型比较
#region 引用类型中自定义类型t比较
Console.WriteLine("----------------我是分割线-----------------------");
Car car1 = new Car()
{
Age = 4,
Color = "Green"
};
Car car2 = new Car()
{
Age = 4,
Color = "Green"
};
Console.WriteLine($"双等于号判断结果为:{(car1 == car2)}");
Console.WriteLine($"Equals判断结果为:{car1.Equals(car2)}");
控制台输出:
二者都是输出False、由于不同的引用实例、所以引用的地址也是不同的、即使数值相同==也会返回False、可能有人会产生疑问,car1 和car2的内容是相同的啊,为什么他俩的比较结果却是为false呢?。原因就在于在Equals是Object中的一个虚方法,而Car类中没有对它进行重写,因此此时调用的仍是父类中的Equals方法。但是父类是无法知道你都有哪些成员字段的,因此返回的是false。要想让他能够比较两个变量的内容是否相同,那就应该重写Equals方法
3、重写Equals并测试
新建类并测试代码如下:
public class TwoDPoint : System.Object
{
public readonly int x, y;
public TwoDPoint(int x, int y)
{
this.x = x;
this.y = y;
}
public override bool Equals(System.Object obj)
{
if (obj == null)
{
return false;
}
TwoDPoint p = obj as TwoDPoint;
if ((System.Object)p == null)
{
return false;
}
return (x == p.x) && (y == p.y);
}
public bool Equals(TwoDPoint p)
{
if ((object)p == null)
{
return false;
}
return (x == p.x) && (y == p.y);
}
public override int GetHashCode()
{
return x ^ y;
}
}
上端调用测试
#region 引用类型中自定义类型t比较
Console.WriteLine("----------------我是分割线-----------------------");
TwoDPoint twoDPoint1 = new TwoDPoint(4, 8);
TwoDPoint twoDPoint2 = new TwoDPoint(4, 8);
Console.WriteLine($"双等于号判断结果为:{(twoDPoint1 == twoDPoint2)}");
Console.WriteLine($"Equals重写后判断结果为:{twoDPoint1.Equals(twoDPoint2)}");
#endregion
控制台输出:
结果显示Equals重写后返回True、==引用的地址不同、所以还是返回False、由此可以证明重写后验证成功。
总结:Equals比较的永远是变量的内容是否相同,而= =比较的则是引用地址是否相同(前提:此种类型内部没有对Equals 或= = 进行重写操作,否则输出可能会有不同)
string类型是个特例,因为他的内部对这两个都进行了重写、以上本人亲测有效、有什么需要改善的欢迎大家提出来、我加以改正。有时候短短几行代码其实要细细研究还是会细思极恐
总而言之还是微软的大佬的给我们封装好了、我们拿来用就可以、但是在用的同时确实也需要有时间研究一下其中原理、其实可以多使用反编译工具研究一下其中代码原理、我这里使用的是ILSPY
来源:https://www.cnblogs.com/ChenBigBao/p/14807569.html


猜你喜欢
- 获取Android的ROOT权限其实很简单,只要在Runtime下执行命令"su"就可以了。// 获取ROOT权限pub
- 前言不得不说,JSP 现在已经是一门十分老旧的技术了,学习编程时,不仅要学习优秀的前言技术,还要对基础有一定的把握,所以学习 JSP 时,我
- activity_list.xml文件代码如下:<?xml version="1.0" encoding=&quo
- 所谓前人栽树,后人乘凉,在此感谢博主的贡献。 原文:边缘凹凸的卡劵效果先上效果图:我实现的效果和原博主实现的效果是不一样的,我是左右边缘凹凸
- 概述:利用AccessibilityService机制实现了一个比较好玩儿的功能,微信朋友圈自动遍历点赞。即通过不断的滚动+点赞实现把每一条
- 日常使用中spring的 @Cacheable 大家一定不陌生,基于aop机制的缓存实现,并且可以选择cacheManager具体提供缓存的
- 在前面的《基于任务的异步编程模式(TAP)》文章中讲述了.net 4.5框架下的异步操作自我实现方式,实际上,在.net 4.5中部分类已实
- bufferedReader.readLine()读到最后发生阻塞最近在做一个imageserver,需求简化后就是使用socket响应HT
- 上一篇写了一下装箱拆箱的定义和IL分析,这一篇我们看下使用泛型和不使用泛型引发装箱拆箱的情况1.使用非泛型集合时引发的装箱和拆箱操作 看下面
- 1.scope 作用域Spring 管理的 bean 是根据 scope 来⽣成的,表示 bean 的作⽤域,共4种,默认值是 single
- 高斯模糊高斯模糊(英语:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop、GIMP以及Paint.NET等图像
- SharedPreferences介绍:SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置
- [java]public static Bitmap getBitmapFromServer(String imagePath) { &nb
- 引言我已经一个多星期没碰过电脑了,今日上班,打开电脑的第一件事就是想着写点什么。反正大家都还沉浸在节后的喜悦中,还没进入工作状态,与其浪费时
- 本文实例讲述了Android实现ListView控件的多选和全选功能。分享给大家供大家参考,具体如下:主程序代码MainActivity.J
- 在开发Android应用程序中,经常会自定义View来实现各种各样炫酷的效果,在实现这吊炸天效果的同时,我们往往会定义很多attr属性,这样
- 一、maven项目的目录结构pom文件定于了一个maven项目的maven配置,一般pom文件的放在项目或者模块的根目录下。maven的遵循
- java -jar设置添加启动参数方法java -jar 参数前后位置说明springboot项目启动的时候可以直接使用java -jar
- 本文实例讲述了JAVA随机打乱数组顺序的方法。分享给大家供大家参考。具体实现方法如下:import java.util.Random;&nb
- 类注解@component 标注类,泛指各种组件,类不属于各种分类的时候,用它做标注。@Service 标注类,声明该类为业务层组件,用于处