声明:本篇博客翻译自: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的更多相关文章

  1. equals变量在前面或者在后面有什么区别吗?这是一个坑点

    我就不废话那么多,直接上代码: package sf.com.mainTest; public class Test { public static void main(String[] args) ...

  2. 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 ...

  3. 【特种兵系列】String中的==和equals()

    1. 小样示例 public static void main(String[] args) { String a = "a" + "b" + 123; Str ...

  4. (转)浅谈Java中的equals和==

    原文地址: http://www.cnblogs.com/dolphin0520/p/3592500.html 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new S ...

  5. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  6. List<T>Find方法,FindAll方法,Contains方法,Equals方法

    假如传入的T是一个类, List<MessageInfos> MessageInfos = new List<MessageInfos>(); MessageInfos= Me ...

  7. 让代码重构渐行渐远系列(3)——string.Equals取代直接比较与非比较

    重构背景及原因 最近由于项目组的人员在不断扩充,导致项目中代码风格各异,大有百花齐放甚至怒放之势.考虑到团队的生存与发展,经过众人多次舌战之后,最终决定项目组根据业务分成几个小分队,以加强团队管理与提 ...

  8. [java] 更好的书写equals方法-汇率换算器的实现(4)

    [java] 更好的书写equals方法-汇率换算器的实现(4) // */ // ]]>   [java] 更好的书写equals方法-汇率换算器的实现(4) Table of Content ...

  9. Equals和ReferenceEquals

    稍微分析下一下两个方法的区别: public static bool Equals(object objA, object objB); public static bool ReferenceEqu ...

  10. 【原创】Java和C#下String类型中的==和equals的原理与区别

    一.Java下 1.几个例子 public static void main(String[] arge) { String str1 = new String("1234"); ...

随机推荐

  1. CMS初步认识

    一CMS本质 [1]基本思想是:分离内容的管理和设计,页面显示的风格和框架存储在模板里.至于页面显示的内容存储在数据库中或一个独立的文件中.当一个用户请求页面时,各部分联合生成一个标准的 HTML 页 ...

  2. CH2101 可达性统计

    题意 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 分析 有向无环图,可以按拓扑序逆序统计答案.可以用bitset维护可达性. 时间复杂度\(O(N ...

  3. streamsets origin 说明

    origin 是streamsets pipeline的soure 入口,只能应用一个origin 在pipeline中, 对于运行在不同执行模式的pipeline 可以应用不同的origin 独立模 ...

  4. 三:背包DP

    01背包问题描述 已知:有一个容量为V的背包和N件物品,第i件物品的重量是weight[i],收益是cost[i]. 限制:每种物品只有一件,可以选择放或者不放 问题:在不超过背包容量的情况下,最多能 ...

  5. 如何查看 ThinkPHP5.1 的升级说明

    如何查看 ThinkPHP5.1 的升级说明 ThinkPHP 官方对于升级历史都有说明,这个官方做的非常不错. 在官方的手册中就有. 比如从 ThinkPHP 5.1.26 升级到 ThinkPHP ...

  6. Appium Desktop介绍-xcodebuild failed with code 65 问题解决

    Appium Desktop介绍-xcodebuild failed with code 65  问题解决 一.Appium Desktop介绍 Appium Desktop是一款用于Mac.Wind ...

  7. Linux环境安装jdk10

    一. 下载jdk 下载方式一:直接在linux上下载 wget --no-check-certificate --no-cookies --header "Cookie: oraclelic ...

  8. oracle 表空间总结

                           表空间总结  一.认识表空间 1:表空间概念: 表空间是数据库中最大的逻辑单位,Oracle数据库采用表空间将相关的逻辑组件组合在一起,一个Oracle数 ...

  9. Centos 6 安装 配置 oracle11g R2

    1.安装centos6.3_64位: 下载地址:http://mirror.bit.edu.cn/centos/6.3/isos/x86_64/ CentOS-6.3-x86_64-bin-DVD1. ...

  10. 【python】使用Python中的urlparse、urllib抓取和解析网页

    一.解析URL 函数urlparse(urlstring [, default_scheme [, allow_fragments]])的作用是将URL分解成不同的组成部分,它从urlstring中取 ...