[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"); ...
随机推荐
- 【.NET】AutoMapper学习记录
在两个不同的类型对象之间传输数据,通常我们会用DTOs(数据传输对象),AutoMapper就是将一个对象自动转换为另一个对象的技术 背景 一些orm框架,在用到Entity的时候有一些开源代码用到了 ...
- 新手,Visual Studio 2013 配置Boost库,如何编译和选择
QuantLib installation in VC++ 2010 and later 参考:http://quantlib.org/install/vc10.shtml 1,到官网下载最新的boo ...
- hasura graphql pg 自定义函数的使用
hasura graphql 的安装可以参考相关项目 创建函数 数据表创建 CREATE TABLE sql_function_table ( id SERIAL PRIMARY KEY, inp ...
- asp.net(C#)链接Oracle连接字符串
在NET环境中链接Oracle数据库有两种组建链接方式: 1)使用OleDB组件是通过Oracle OleDB驱动程序(OraOLEDB.dll)连接和访问Oracle数据库2)使用System.Da ...
- jeecms 单页静态化方法
在论坛上去搜,都说可以需要在模型中配置增加字段,看了云里雾里,调试源代码发现原因,方法如下: 步骤一:改模型 模型管理->"单页“栏目模型->添加: channelStatic( ...
- Visual Studio环境变量、工作目录、vc++目录、 命令等 的配置和作用
在调试 Visual Studio 2008 程序时,经常有一些动态链接库(即 dll 文件)需要加载到工程里,这样才能依赖第三方库进行程序调试. 这些动态链接库,往往都是测试版本或是开发中的版本,或 ...
- Hibernate SQL 查询
本文转载自:https://www.cnblogs.com/li3807/p/6358386.html Hibernate 支持使用原生的SQL查询,使用原生SQL查询可以利用某些数据库特性,原生SQ ...
- 测试用例文件的存放和创建,对page objeck的理解
如:(注意我下面这种要用eval函数取拼接的)
- Oracle表空间知识
Oracle表空间知识 一,创建临时表空间 CREATE temporary TABLESPACE TEMP_PNLREPORT tempfile '/oradata2/ORCL/temp_pnlre ...
- Selenium2+python自动化64-100(大结局)[已出书]
前言 小编曾经说过要写100篇关于selenium的博客文章,前面的64篇已经免费放到博客园供小伙伴们学习,后面的内容就不放出来了,高阶内容直接更新到百度阅读了. 一.百度阅读地址: 1.本书是在线阅 ...