C# 中 == 和 .Equals() 之间的区别
C# 中 == 和 .Equals() 之间的区别
概述
在本文中,您将了解C# 中 == 和 .Equals() 之间的区别。== 和 .Equals() 既用于两个值类型数据项的比较,也用于两个引用类型数据项的比较。本文将解释这两者之间的基本区别。== 比较内容,也比较引用标识,而 .Equals() 只比较内容。
The
==Operator compares the reference identity as well as contents while the
.Equals() method compares only contents.
以下是一些示例,以了解这两者之间的区别。
案例 1:同时使用 == 和 .Equals() 进行值类型比较
当您使用 == 或使用 .Equals() 比较值类型或原始数据类型( int 、double 、float等)时,比较始终基于内容。如果两个变量的值的内容相同,则返回true,否则返回false。
示例,值类型的比较:
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
当我们使用 == 比较 x 和 2.0 时,值 2.0 被认为是 2;而使用 .Equals() 方法时,值 2.0 不被认为是 2,所以它们的输出不同。在此示例中,== 操作符对值类型执行按位相等比较,如果返回true,则意味着被比较的对象具有相同的二进制表示;而 .Equals() 方法只是比较内容,所以它返回 false。
案例 2:同时使用 == 和 .Equals() 的引用类型比较
当您比较对象(即引用类型)时,它们会根据引用(内部的内存指针)进行比较。
示例,引用类型的比较:
Employee obj1 = new Employee();
obj1.Name = "Tutorialsrack";
Employee obj2 = new Employee();
obj2.Name = "Tutorialsrack";
Console.WriteLine(obj1 == obj2); //False
Console.WriteLine(obj1.Equals(obj2)); //False
Employee obj3 = obj1;
Console.WriteLine(obj1 == obj3); //True
Console.WriteLine(obj1.Equals(obj3)); //True
在上面的示例中,我们创建了两个Employee
类对象(obj1 和 obj2 ),并使用 == 和 .Equals() 比较这两个对象。两个对象的内容虽然相同,但它们都返回了 false 。因为是对它们内部的内存指针进行比较,它们引用的是不同的实例。
接着,我们又"创建"了Employee
类的一个对象(obj3),并使用 == 和 .Equals() 比较 obj1 和 obj3,它们都将返回了 true。因为obj1和obj3是对同一个实例的引用,具有相同的内存指针。
案例 3:同时使用 == 和 .Equals() 进行字符串和对象比较
在 C# 中,如果字符串的内容相同,那么认定它们指向相同的内存位置, == 和 .Equals() 都将返回 true。
//基于内容比较两个字符串
//通过双引号初始化的 string 对象 在堆中存储,如果字符串的内容相同,那么认定它们指向相同的内存位置
object str1 = "tutorialsrack";
object str2 = "tutorialsrack";
Console.WriteLine(str1 == str2); //True
Console.WriteLine(str1.Equals(str2)); //True
//基于引用的比较:
//string 对象 不在堆中存储,即 string 对象是一个普通的引用类型
object str3 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });
object str4 = new string(new char[] { 't', 'u', 't', 'o', 'r', 'i', 'a', 'l' });
Console.WriteLine(str3 == str4); //False,基于引用
Console.WriteLine(str3.Equals(str4)); //True,基于内容
//== 运算符进行类型检查;.Equals() 方法不进行类型检查
string str7 = "tutorialsrack";
object obj = "tutorialsrack";
Console.WriteLine(str7 == obj); //True,编译时显示警告信息
Console.WriteLine(str7.Equals(obj)); //True
//== 运算符处理 null 而 .Equals() 方法不处理
string str5 = null;
string str6 = null;
Console.WriteLine(str5 == str6); //True,两个都是 null 时,返回 true
Console.WriteLine(str5.Equals(str6)); //此处抛出错误 NullReferenceException
在上面的示例中,当我们为“str1”赋值时,它会创建一个字符串对象,并且在堆中存储“tutorialsrack” 。当我们为“str2”赋值时,会分配一个不同的对象。因此,本应该使用“引用类型的规则”来比较“str1”和“str2”。但 == 和 .Equals() 值却是 true,因为在 C# 中,如果字符串的内容相同,那么认定它们指向相同的内存位置。
何时使用 == 运算符和 .Equals() 方法
==
运算符是 C# 运算符,而 .Equals() 方法是多态方法。换句话说, == 是一种语言特征,而 .Equals() 它是 OOP 在遵循多态方面的一个特征点。
因此,判断何时使用 == 运算符和 .Equals() 方法:
- 使用 == 运算符,当您需要进行一些技术比较时,例如对内容进行类型检查并处理 null 值。
- 使用 .Equals() 方法,当您需要进行一些语义比较(例如内容比较)并且不关心 null 值时。
C# 中 == 与 .Equals() 之间的区别
# | == 运算符 | .Equals() 方法 |
---|---|---|
用法 | 基于技术 | 基于语义的 |
值类型 | 基于内容的比较以及按位比较 | 基于内容的比较 |
对象类型 | 基于引用的比较 | 基于引用的比较 |
string | 基于内容的比较 | 基于内容的比较 |
非堆中存储的的 string | 基于引用的比较 | 基于内容的比较 |
类型检查 | 在编译期间 | 在运行时 |
空值 | 它处理空值 | 它不能处理空值 |
我希望这篇文章能帮助你理解C# 中 == 运算符和 .Equals() 方法之间的区别。
重载 == 与 .Equals()
C# 中有两种不同的相等:值相等和引用相等。
-
值相等,是大家普遍理解的,在意义上的相等:它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。
-
引用相等,意味着要比较的不是两个对象本身,而是两个对象的引用,判断这两个“对象引用”是否引用的是同一个对象。
对于引用相等,.Net 提供了
System.Object.ReferenceEquals(objA, objB);
方法来判是否引用相等;如果objA
是与objB
相同的实例,或如果两者均为 null,则为true
,否则为false
。
.Equals()
-
Equals 是一个虚方法,允许任何类重写其实现。表示某个值(本质上可以是任何值类型)或一组值(如复数类)的任何类都应该重写 Equals。
即,.Equals() 是冲着判断值相等去的,表示某个值或一组值的任何类都应该重写 Equals。。
-
Equals 的新实现不应该引发异常。
-
建议重写 Equals 的任何类同时也重写 System.Object.GetHashCode。
-
除了实现 Equals(对象)外,还建议所有的类为自己的类型实现 Equals(类型)以增强性能。
== 运算符
- 默认情况下,== 通过判断两个引用是否指示同一对象来测试引用是否相等,因此引用类型不需要实现运算符 == 就能获得此功能。
- 当类型不可变时,意味着实例中包含的数据不可更改,此时通过重载运算符 == 来比较值是否相等而不是比较引用是否相等可能会很有用,因为作为不可变的对象,只要它们具有相同的值,就可以将它们看作是相同的。
- 建议不要在非不可变类型中重写运算符 ==。
- 重载的运算符 == 实现不应引发异常。
- 重载运算符 == 的任何类型还应重载运算符 !=。
- 运算符 == 的重载中的常见错误是使用
(a == b)
、(a == null)
或(b == null)
来检查引用相等性。这会导致调用重载的运算符 ==,从而导致无限循环。应使用 ReferenceEquals 或将类型强制转换为 Object 来避免无限循环。
关于重载,详情参阅:Equals() 和运算符 == 的重载准则(C# 编程指南)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?