浅析C#中的“==”和Equals
1.“==”和Equals两个真的有关联吗?
对于“==”和Equals大多数网友都是这样总结的:
- “==” 是比较两个变量的值相等。
- Equals是比较两个变量是否指向同一个对象。
如:这篇文章,并以这篇文章中的例子为例。
public class Person
{
public Person(string name)
{
this.Name = name;
} public string Name { get; set; }
} static void Main(string[] args)
{
string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
Console.WriteLine(a == b); //true
Console.WriteLine(a.Equals(b)); //true object g = a;
object h = b;
Console.WriteLine(g == h); //false
Console.WriteLine(g.Equals(h)); //true Person p1 = new Person("jia");
Person p2 = new Person("jia");
Console.WriteLine(p1 == p2); //false
Console.WriteLine(p1.Equals(p2)); //false
Person p3 = new Person("jia");
Person p4 = p3;
Console.WriteLine(p3 == p4); //true
Console.WriteLine(p3.Equals(p4)); //true Console.ReadKey();
}
假如上述结论正确,“==” 是比较两个变量值相等,那么下面这句代码就不应该为True.
Console.WriteLine(a == b); //true
很明显,上面的两个字符串变量:a,b 是指向两个不同的对象,即它们在栈空间存储的内存地址也是不同的。但为毛它们就相等了呢?
2.什么是运算符重载?
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。打个简单的比方:“+” 运算符,在“+” 两
边全为数值类型的变量时,“+” 运算符表示数学上的“+” 意义。若“+” 运算符两边只要有一个为字符串类型,那么“+” 运算符就表示连接
字符串的意义。这样的运算符重载实例有很多,那么这跟本文主题有毛关系?我想说的是,上面字符串变量:a , b 就是因为String类
重载了运算符 “==”,看下列源代码:
public static bool operator == (String a, String b)
{
return String.Equals(a, b);
}
public static bool operator != (String a, String b)
{
return !String.Equals(a, b);
}
很明显String类中真的重载了“==”运算符,并且不止 “==” 还有 “!=” 哦。并且在重载运算符方法内部直接调用String类中的Equals方法,
源代码如下:
public static bool Equals(String a, String b)
{
if ((Object)a==(Object)b)
{
return true;
} if ((Object)a==null || (Object)b==null)
{
return false;
} if (a.Length != b.Length)
return false; return EqualsHelper(a, b);
}
由上可得:“==” 运算符并不一定是比较两个变量中存储的值是否相等,这要看当前运算符在当前这个类型中是否写有重载。
3.Equals的重写
还是上面例子:
string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
Console.WriteLine(a == b); //true
Console.WriteLine(a.Equals(b)); //true
由上可知:a ,b 为两个不同的对象。但Equals为True,则上述:“Equals是比较两个变量是否指向同一个对象“这一结论不成立。原因
看String类中的Equals方法:
public override bool Equals(Object obj)
{
if (this == null) //this is necessary to guard against reverse-pinvokes and
throw new NullReferenceException(); //other callers who do not use the callvirt instruction String str = obj as String;
if (str == null)
return false; if (Object.ReferenceEquals(this, obj))
return true; if (this.Length != str.Length)
return false; return EqualsHelper(this, str);
} public bool Equals(String value)
{
if (this == null) //this is necessary to guard against reverse-pinvokes and
throw new NullReferenceException(); //other callers who do not use the callvirt instruction if (value == null)
return false; if (Object.ReferenceEquals(this, value))
return true; if (this.Length != value.Length)
return false; return EqualsHelper(this, value);
}
由上面可知String类中不仅重写了Object中的Equals还有自己的Equals方法,但是实现代码几乎是一样的。比较类型,内存地址,
实际值,从而获得最终的结果。所以Equals不一定就是单一的比较引用地址是否相同,更何况我们还可以重写和自定义。但是重写
Equals也有需要注意的地方,就是如果你需要用到HashMap,HashSet,Hashtable那么你也需要重写GetHashCode()。
4.为什么有了“==”还要有Equals?
中国有一句话:“任何事物的存在必然有他存在的道理和价值”,同理“==”和Equals也是一样。“==” 在引用类型中最基本的实现就是去比
较两对象的内存地址是否一致,一致则相等反之则不等。这样的实现很明显是从硬件角度去思考的,如果两个对象相等即为同一个对象,
那么它们在内存中的地址必然相等。但很多时候 “行为(方法)“ 是取决于我们去观察世界的角度。 如:String类型我们申明一个字符
串更在意的是字符串所具有的实际值,而不是在意两个对象在内存中是创建了一次还是两次(即内存地址是否相等),只要它们所具有的
实际值是相等的那么我们就认为它们是相等,这是从生活业务逻辑中去理解的而不是从机器角度上去理解的。当然上面声明相同的字符串
变量是创建一次还是两次我想:” 常量池(或字符串拘留池)“ 已经给了我们最好的解决方案。
5.“==”和Equals到底什么关系?
”==“ 运算符和Equals它们其实是互补关系。因为:”==“ 运算符主要实现形式是站在 ”计算机角度(或者说硬件角度)” 上去实现的,
而Equals是站在常用的业务场景或者是特定的业务场景下去实现的,二者没有什么必然的联系,是根据自己的业务需要选择不同方法而
已。所以Object里面的Equals是virtual,很多类中都重写了它,并真正达了在当前类型中所需的特定行为,即:多态。所以就不难解释
上面:
object g = a;
object h = b;
Console.WriteLine(g == h); //false
Console.WriteLine(g.Equals(h)); //true
因为Object中没有实现重载运算符:“==”,所以当前“==”的比较方式是比较两变量在栈空间存储的内存地址是否相同。而Equals则是
调用String类中的Equals,原因g变量在运行中它实际上指向一个字符串对象的,而当前的Object类型只是Visual studio和编译器的行
为,即:还是多态。
最后任何东西都有它的规则:”==“和Equals也不例外,详细资料请点击:跳转至MSDN。
浅析C#中的“==”和Equals的更多相关文章
- 浅析c#中==操作符和equals方法
在之前的文章中,我们讲到了使用C#中提供的Object类的虚Equals方法来判断Equality,但实际上它还提供了另外一种判断Equality的方法,那就是使用==运算符.许多童鞋也许会想当然的认 ...
- 通过源码浅析Java中的资源加载
前提 最近在做一个基础组件项目刚好需要用到JDK中的资源加载,这里说到的资源包括类文件和其他静态资源,刚好需要重新补充一下类加载器和资源加载的相关知识,整理成一篇文章. 理解类的工作原理 这一节主要分 ...
- 浅析Java7中的ConcurrentHashMap
引入ConcurrentHashMap 模拟使用hashmap在多线程场景下发生线程不安全现象 import java.util.HashMap; import java.util.Map; impo ...
- java中hashcode()和equals()的详解
今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享(zhaoxudong 2008.10.23晚21.36). 1. 首先equals()和hashc ...
- 浅析Java中的final关键字
浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...
- 浅析mongodb中group分组
这篇文章主要介绍了浅析mongodb中group分组的实现方法及示例,非常的简单实用,有需要的小伙伴可以参考下. group做的聚合有些复杂.先选定分组所依据的键,此后MongoDB就会将集合依据选定 ...
- 浅析py-faster-rcnn中不同版本caffe的安装及其对应不同版本cudnn的解决方案
浅析py-faster-rcnn中不同版本caffe的安装及其对应不同版本cudnn的解决方案 本文是截止目前为止最强攻略,按照本文方法基本可以无压力应对caffe和Ross B. Girshick的 ...
- 浅析JS中的模块规范(CommonJS,AMD,CMD)////////////////////////zzzzzz
浅析JS中的模块规范(CommonJS,AMD,CMD) 如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. ...
- 浅析Java中的访问权限控制
浅析Java中的访问权限控制 今天我们来一起了解一下Java语言中的访问权限控制.在讨论访问权限控制之前,先来讨论一下为何需要访问权限控制.考虑两个场景: 场景1:工程师A编写了一个类ClassA,但 ...
随机推荐
- 问题解决——OpenGL超级宝典 关于gltDrawTorus的错误解决
看OpenGL超级宝典的时候,遇到一个函数 “gltDrawTorus”,在TRANSFORM和SPHEREWORLD中都有用到.但是一开始在自己写示例代码里时却没法使用,而在作者的代码目录结构下却可 ...
- sql 执行动态语句
没看明白,可不可以描述清楚点哦 收获园豆:5 回复 | artwl | 专家六级 |园豆:16486 | 2011-09-01 09:10 exec (select top 2 * from pub ...
- Python的逻辑运算符and小析
近期突然对验证码的识别感兴趣了,然后就研究了一些图像识别和处理的资料,其中有一种图像处理是关于字体的细化和骨架提取的,但是这种算法没有现成的java代码实现,那些号称的java版代码多半都是效果很差或 ...
- java charset detector
https://code.google.com/p/juniversalchardet/downloads/list java移植mozilla的编码自动检测库(源码为c++),准确率高. 通过svn ...
- 1维FDTD仿真
FDTD基本原理是把麦克斯韦方程胡两个矢量旋度方程写成差分形式,利用数值方法求其解. 假设电磁场传播方向为x轴方向,电场只有z轴方法分量,磁场只有y轴方向分量.两个旋度方程可以写成下列形式 电场.磁场 ...
- [转载]ExtJs4 笔记(8) Ext.slider 滚轴控件、 Ext.ProgressBar 进度条控件、 Ext.Editor 编辑控件
作者:李盼(Lipan)出处:[Lipan] (http://www.cnblogs.com/lipan/)版权声明:本文的版权归作者与博客园共有.转载时须注明本文的详细链接,否则作者将保留追究其法律 ...
- python刷题专用函数。。
无它,非bin()莫属. bin(x) Convert an integer number to a binary string. The result is a valid Python expre ...
- 2014 Super Training #1 F Passage 概率DP
原题: HDU 3366 http://acm.hdu.edu.cn/showproblem.php?pid=3366 本来用贪心去做,怎么都WA,后来看网上原来是一个DP题. 首先按P/Q来做排 ...
- UESTC 31 饭卡(Card) --背包问题
背包问题. 思路:如果m<5,此时也不能消费,所以此时答案为m m>=5: 求出背包容量为m-5,买前n-1样便宜的菜(排个序)的最大价值(即最大消费,即消费完后剩余值最接近5)最后减去最 ...
- 给定一个整数实现奇偶bit位互换
1.分别取出所有奇数bit位和偶数bit位 0x55555555(对应二进制奇数bit位为1,偶数bit位全为0)&num 0xaaaaaaaa(对应二进制即偶数bit位为1,奇数bit位全为 ...