当前位置: 首页 > article >正文

C#中相等比较 == 和 Equal函数 对比

1.== 运算符

== 是一个运算符,用于比较两个值是否相等。对于值类型(如 intfloatdouble 等),== 直接比较两个值是否相同。对于引用类型(如类和数组),== 比较两个引用是否指向内存中的同一个对象。

2.Equal函数

C#中所有类型(自定义的也一样)都继承自System.Object类,因此所有类型都有Equal这个比较方法,Equal一般会来自两个地方

第一个地方

public virtual bool Equals(object obj)
//自己可以重写的噢

这是从 System.Object 继承而来的方法,它接受一个 object 类型的参数。默认情况下,这个方法执行引用相等性检查,即它检查两个对象是否引用同一个对象实例。

第二个地方

public bool Equals(T other)

这是一个泛型重载,它接受一个与当前对象类型相同的参数。这个重载通常在实现了 IEquatable<T> 接口的类中被重写,用于执行值相等性检查。

如Int类型的:(override是重写,这个函数Equals(object obj)它还可以重写的)

对于引用类型,Equals(object obj) 默认比较的是引用,即检查两个对象是否是同一个实例。对于值类型,它比较的是值。

3.string、结构体struct比较

对于 string、 结构体struct类型,使用 == 运算符和 Equals 方法都是进行值比较,它们的行为是一致的。

4.不同

==运算符可以处理null,而Object.Equals 操作变量为null时会报错,如下

Ap re = null;
Ap res = new Ap();

if(re.Equals(res))
{
   Console.WriteLine("相同");
}


未经处理的异常:  System.NullReferenceException: 未将对象引用设置到对象的实例。

因此,使用Equals比较时请养成好习惯,记得判空

Ap re = null;
Ap res = new Ap();

if(re != null)
{
    if(re.Equals(res))
    {
       Console.WriteLine("相同");
    }
}

参考:

比较 .NET 中的字符串 - .NET | Microsoft Learn

C# 中 == 和 .Equals() 之间的区别 - 误会馋 - 博客园(强烈推荐一读

纠错 1

int x = 2;
int y = 2;

Console.WriteLine(x == y); //True
Console.WriteLine(x.Equals(y)); //True

Console.WriteLine(x == 2.0); //True
Console.WriteLine(x.Equals(2.0)); //False

Console.WriteLine(x == 2.0); //True

这里 == 操作符比较 int 类型的 x 和 double 类型的字面量 2.0。在C#中,int 类型可以隐式转换为 double 类型,这里发生了隐式转换,因此 2 被转换为 2.0,然后比较这两个值是否相等,结果是 True

Console.WriteLine(x.Equals(2.0)); //False

这里 Equals() 方法的行为与 == 操作符不同。Equals() 方法在没有被重写的情况下,对于 int 类型的 x 和 double 类型的 2.0,会返回 False,因为 Equals() 方法默认比较的是引用类型的引用是否相等,而 int 和 double 是不同的类型,它们在内存中的存储和表示也不同。即使它们的数值相同,Equals() 方法也会因为类型不匹配而返回 False。

如图可以看到编译器这里提示调用的函数,前一个Equal参数是同类型的int,这里的Equal参数类型时object

误区 2

在 C# 中,如果字符串的内容相同,那么认定它们指向相同的内存位置,这里是很多人容易犯错的误区,认为出现的字符串都是同一个对象,即堆区同一个地址;大部分情况是,因为string 类型在C#中有一个特殊的内部机制,称为字符串内部缓存。对于字面量字符串或者在编译时已知的字符串,编译器会尝试重用相同的字符串对象,这意味着即使它们在代码中被多次声明,它们实际上可能指向同一个对象。

有同学可能对字面量不理解,字面量是直接在代码中给出的值,而不是通过变量名或计算得到的

"ni hao"        //这是字面量,直接展示的

10        //也是字面量、

int a = 9;//a是变量,9是字面量

因此会有如下的代码对比

    public class Ap
    {
        public string a;
    }


            Ap ap1 = new Ap();
            ap1.a = "we";
            Ap ap2 = new Ap();
            ap2.a = "we";

            Console.WriteLine(ap1.a == ap2.a);//True
            Console.WriteLine(ap1.a.Equals(ap2.a));//True


            string str1 = "Compare";
            string str2 = "Compare";
            Console.WriteLine(str1 == str2);//True
            Console.WriteLine(str1.CompareTo(str2));//0
            Console.WriteLine(String.Compare(str1, str2));//0
            Console.WriteLine(str1.Equals(str2));//True
            Console.WriteLine(String.Equals(str1, str2));//True
            Console.WriteLine(Object.ReferenceEquals(str1, str2));//True

字面量的字符串都是相同的,因为引用了同一个地址,但是这并不适用于通过 new 关键字显式创建的字符串对象,因为显式创建的字符串对象总是不同的实例。

如下:


            object str1 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });
            object str2 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });
            Console.WriteLine(str1 == str2);  //False
            Console.WriteLine(str1.Equals(str2));  //True



            string str3 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });
            string str4 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });
            Console.WriteLine(str3 == str4);  //True
            Console.WriteLine(str3.Equals(str4));  //True

Console.WriteLine(str1 == str2); //False

这里使用 == 操作符比较 str1 和 str2。由于 str1 和 str2 是通过 new string(new char[] {...}) 创建的两个不同的对象实例,即使它们的内容相同,它们在内存中的地址也是不同的。因此,== 操作符返回 False,因为它比较的是对象的引用。

Console.WriteLine(str1.Equals(str2)); //True

Equals 方法在 string 类型中被重写,所以父类object对象调用的是子类string重写后的String.Equals(object obj)方法,该方法比较的同样是内容而非引用

我们之前说过无论是==还是Equal在比较字符串时总是值比较,看到str3和str4比较,因此值相等自然就相等。


http://www.kler.cn/a/457388.html

相关文章:

  • 下载linux aarch64版本的htop
  • HackMyVM-Airbind靶机的测试报告
  • springcloud篇3-docker需熟练掌握的知识点
  • 直播预告丨社区年度交流会 《RTE 和 AI 融合生态洞察报告 2024》发布
  • Leetcode 第426场周赛分析总结
  • word文档中的文档网格——解决相同行间距当显示出不同行间距的情况
  • 在Ubuntu下通过Docker部署Cloudflared Tunnel服务器
  • SpringBoot整合springmvc
  • 遗传算法——附python实现与各方法的作用与修改
  • 【强化学习】深度确定性策略梯度算法(DDPG)详解(附代码)
  • 碰一碰发视频矩阵系统源码搭建,支持OEM
  • Qt仿音乐播放器:QFileDialog添加本地文件
  • BMS存储模块的设计
  • idea 禁用/关闭 sonarlint 后台自动分析(默认开启可能会引起idea卡顿)
  • 【K8s】专题十五(6):Kubernetes 网络之 Pod 网络调试
  • Netty 2024 常见面试题
  • 个人用途虚拟机VM 17安装Ubuntu 16.04.5 图解
  • 大数据面试笔试宝典之Spark面试
  • Java网约车项目实战:实现抢单功能详解
  • golangb并发,Sync包中Mutes,WaitGroup, NewCond的适应
  • 八大排序——直接插入排序
  • 几款性能优秀的差分进化算法DE(SaDE、JADE,SHADE,LSHADE、LSHADE_SPACMA、LSHADE_EpSin)-附Matlab免费代码
  • CAN201 Introduction to Networking(计算机网络)Pt.2 传输层
  • 行为树详解(5)——事件驱动
  • 跨域请求问题
  • 一种基于动态部分重构的FPGA自修复控制器