[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"); ...
随机推荐
- [BZOJ2727][HNOI2012]双十字
bzoj luogu sol 先预处理从每个点出发向上/下/左/右能延伸多长. 考虑怎么计算答案.我们只要枚举中轴线,再枚举上方的十字交点,枚举下方的十字交点,然后算答案即可. 考虑一个左右宽的最小值 ...
- html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感)
html页面下拉列表中动态添加后台数据(格式化数据,显示出数据的层次感) 效果图: 运行原理和技术: 当页面加载完毕,利用jquery向后台发送ajax请求,去后台拼接<select>&l ...
- ACM学习历程—HDU2476 String painter(动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=2476 题目大意是给定一个起始串和一个目标串,然后每次可以将某一段区间染成一种字符,问从起始串到目标串最少需要染多 ...
- Libusb学习
1.参考:http://www.cnblogs.com/Daniel-G/archive/2013/04/22/3036730.html https://baike.so.com/doc/506541 ...
- list_for_each与list_for_each_entry具体解释
一.list_for_each 1.list_for_each原型#define list_for_each(pos, head) \ for (pos = (head)->next, ...
- 系列文章--oracle简单入门教程
oracle入门很简单:八.oracle数据表 1.创建oracle数据表创建oracle数据表的语法如下: create table命令用于创建一个oracle数据表:括号内列出了数据表应当包含的列 ...
- CCFLOW5 SDK 模式 开发环境配置
在群里和论坛里问了N次都没有人回答,最终在QQ好友[冥(276669806) ]的帮助下成功配置了SDK开发环境.现将具体配置步骤分享给大家.1.打开VS2010 新建一个网站项目2.将CCFlow\ ...
- Oracle.DataAccess.dll 部署安装
Oracle.DataAccess.dll 要拷贝到项目发布目录 项目发布的时候,还必须要拷贝以下几个文件在运行目录1.oci.dll 2.oraociicus11.dll 3.OraOps11w.d ...
- java 方法(函数)
所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 一般情况下,定义一个方法的语法是: 其中: 1. 访问修饰符:方法允许被访问的权限范围, 可以是 public.protected.p ...
- 黄聪:中国大陆的所有IP段,中国电信所有IP段、中国铁通所有IP段、中国网通所有IP段。
中国大陆的所有IP段,中国电信所有IP段.中国铁通所有IP段.中国网通所有IP段. 中国大陆的所有IP段: 47.153.128.0 47.154.255.25558.14.0.0 58.25.255 ...