[C#] == VS Equals
声明:本篇博客翻译自:https://www.codeproject.com/Articles/1111680/equalsequals-VS-Equals-in-Csharp
由于水平(技术水平+英语理解能力)有限/不足,肯定会有所疏漏/错误,请及时指正。
介绍:
在C#中,可以使用“==”和一个可重载的"Equals()"方法来对变量进行比较。但是很多开发者并不知道两者之间的区别。在这篇博客中将讨论两者之间的区别和两者的使用场景。"=="和"Equals()"比较没有区别除了在做string的比较时。
比较规则:C#中的比较无非是对值类型和引用类型进行比较。当对值类型进行比较时,比较的是值类型的“内容”;当对引用类型进行比较时,比较的是对象的引用是否相同(内存地址)而不是“内容”。上述规则对"=="和"Equals()"均适用。
场景一:值类型比较
当对值类型(int, double, byte etc)进行比较时, "=="和"Equals()"都是基于值类型的内容比较。当值类型的内容相同,则两者相等。
Console.WriteLine("Value Type Compare...");
int i = ;
int y = ;
Console.WriteLine(i == y); // true
Console.WriteLine(i.Equals(y)); // true
场景二:引用类型比较
当对引用类型(object, interface)进行比较时,比较的是引用(内存地址)是否相同,下面代码中obj1和obj2使用"=="和“Equals”进行比较,结果为:false.尽管两个对象的内容一样的。但是内容地址不一样。
class Customer
{
public string Name { get; set; }
} Customer obj1 = new Customer();
obj1.Name = "Jimmy-Yang"; Customer obj2 = new Customer();
obj2.Name = "Jimmy-Yang"; Console.WriteLine(obj1 == obj2); // false
Console.WriteLine(obj1.Equals(obj2)); // false
如果obj1与obj2指向同一个引用(内存地址)。
Customer obj1 = new Customer();
obj1.Name = "Jimmy-Yang"; Customer obj2 = obj1; Console.WriteLine(obj1 == obj2); // true
Console.WriteLine(obj1.Equals(obj2)); // true
场景三:string比较
string类型是引用类型,那么下面代码中"str"创建一个string对象,并且在堆内存块上存储"test"字符。当创建str1后,虽然存储的内容一样,但是应该存储在不同的内存区域。
object str = "test";
object str1 = "test";
Console.WriteLine(str == str1); // true
Console.WriteLine(str.Equals(str1)); // ture
执行结果发现str与str1是相等的。这是为什么呢?
注意:C#的string类型遵循一条内部的规则。如果str与str1的内容相同,则两者指向系统的的内存地址。因此“==”和"Equals"会返回true。
但是注意下面的代码,我们创建了一个单独对象,然后赋值给string类型。此时“==”比较将返回false,Equals()将返回true。这是两者一个不同的地方。
object str = new string(new char[] { 't', 'e', 's', 't' });
object str1 = new string(new char[] { 't', 'e', 's', 't' });
Console.WriteLine(str == str1); // false
Console.WriteLine(str.Equals(str1)); // true
场景四:编译时VS运行时
两者之间在做类型检查时的区别。==在编译时做类型检查;Equals()在运行时做类型检查。请看下面的代码,在“==”会有一个警告信息。

场景五:NULL
当比较的对象为null时,“==”不会抛出异常,"Equals()"比较null对象时,会直接crash。

使用场景
"=="是C#提供的一个运算符,“Equals()”是基类提供的一个虚方法,可以在子类中继承,并编写自身比较逻辑。换句话说,“==”是一个C#的一个特性,而Equals是OOP的一个特性。两者的区别一个基于单纯的内容和引用(内存地址)比较。另一种是基于语义(Semantics, 此处我翻译成语义,其实更确切的应该是对象之间的含义)上的比较。例如:1 <> 10 (从技术层面上讲),但是现实生活中,1元=10角,此时1=10在含义上。
- 如果单纯从技术层面上比较请使用“==”;
- 如果从语义上比较(例如:1元=10角),你需要使用Equals方法并提供合适的比较逻辑。
总结
请看下面的表格:
| == | Equals | |
| Usage | Technical based | Semantic based |
| Value types | Content based Comparison | Content based Comparison |
| Objects | Reference based Comparison | Reference based Comparison |
| String | Content based Comparison | Content based Comparison |
| String with no interning | Reference based Comparison | Content based Comparison |
| Type checking | Compile time | Run time |
| Nulls | Works | Can crash |
[C#] == VS Equals的更多相关文章
- equals变量在前面或者在后面有什么区别吗?这是一个坑点
我就不废话那么多,直接上代码: package sf.com.mainTest; public class Test { public static void main(String[] args) ...
- How to implement equals() and hashCode() methods in Java[reproduced]
Part I:equals() (javadoc) must define an equivalence relation (it must be reflexive, symmetric, and ...
- 【特种兵系列】String中的==和equals()
1. 小样示例 public static void main(String[] args) { String a = "a" + "b" + 123; Str ...
- (转)浅谈Java中的equals和==
原文地址: http://www.cnblogs.com/dolphin0520/p/3592500.html 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new S ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- List<T>Find方法,FindAll方法,Contains方法,Equals方法
假如传入的T是一个类, List<MessageInfos> MessageInfos = new List<MessageInfos>(); MessageInfos= Me ...
- 让代码重构渐行渐远系列(3)——string.Equals取代直接比较与非比较
重构背景及原因 最近由于项目组的人员在不断扩充,导致项目中代码风格各异,大有百花齐放甚至怒放之势.考虑到团队的生存与发展,经过众人多次舌战之后,最终决定项目组根据业务分成几个小分队,以加强团队管理与提 ...
- [java] 更好的书写equals方法-汇率换算器的实现(4)
[java] 更好的书写equals方法-汇率换算器的实现(4) // */ // ]]> [java] 更好的书写equals方法-汇率换算器的实现(4) Table of Content ...
- Equals和ReferenceEquals
稍微分析下一下两个方法的区别: public static bool Equals(object objA, object objB); public static bool ReferenceEqu ...
- 【原创】Java和C#下String类型中的==和equals的原理与区别
一.Java下 1.几个例子 public static void main(String[] arge) { String str1 = new String("1234"); ...
随机推荐
- 我的AOP那点事儿--2
在<我的AOP那点事儿-1>中,从写死代码,到使用代理:从编程式AOP到声明式AOP.一切都朝着简单实用主义的方向在发展.沿着 Spring AOP 的方向,Rod Johnson(老罗) ...
- ACCESS_TOKEN与FRESH_TOKEN
OAuth1.0中的access_token过期时间通常很长,安全性差.于是OAuth2.0推出了refresh_token. OAuth2.0中,客户端用账户名,密码经过一定方式(比如先请求code ...
- TCP/IP详解与OSI七层模型
TCP/IP协议 包含了一系列构成互联网基础的网络协议,是Internet的核心协议.基于TCP/IP的参考模型将协议分成四个层次,它们分别是链路层.网络层.传输层和应用层.下图表示TCP/IP模型与 ...
- Kubernetes才是微服务和DevOps的桥梁
一.从企业上云的三大架构看容器平台的三种视角 一切都从企业上云的三大架构开始. 如图所示,企业上的三大架构为IT架构,应用架构和数据架构,在不同的公司,不同的人,不同的角色,关注的重点不同. 对于大部 ...
- 【转】Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)
原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182646 本例通过在单文档程序的视图中添加WM_LBUTTONCLICK消息处理函数 ...
- oracle之 监听器无法启动的几个原因总结
1)防火墙没关 2)/etc/hosts配置问题,有可能误删了127.0.0.1的默认记录,添加默认记录 [root@rac02 ~]# cat /etc/hosts127.0.0.1 localho ...
- bzoj2431逆序对数列
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2431 很容易想到n^3的做法.就是前 i 个数用第 i 个数最多能 i - 1 个逆序对,所 ...
- redis事务,分布式锁
事务:一组命令集合 主要命令multi 和exec multi set a 1 sadd s1 a ...... exec 错误处理 (1)语法错误 127.0.0.1:6379> multi ...
- 众安尊享e生·新全保通2017成人精选版60岁以后续保的保费清单
尊享e生·新全保通2017成人精选版--有社保的费用 https://www.zhongan.com/p/83881372?channelEnName=health 61-65男性 13028女性 8 ...
- php soap实例讲解
一,什么是soap,什么是wsdl,为什么要用他们 SOAP是基于XML和HTTP通信协议,xml各种平台,各种语言都支持的一个种语言.http呢它得到了所有的因特网浏览器及服务器的支持. WSDL ...