c#中==与Equals区别

一、重载和重写的调用区别

==是方法重载(参数个数或参数类型不同),在实际调用中会根据引用类型(不是实际对象)来调用,如Father f = new Son()  通过f会调用到 ==(Father, Father)重载,而不是==(Son, Son)重载

Equals是方法重写,在实际调用中会根据实际对象(不是引用类型)来调用,如Father f = new Son()  通过f会调用到 Son.Equals(object)方法,而不是Father.Equals(object)方法

二、所有类型基类object和值类型基类ValueType

首先对于基类object,它的==是进行同一性的比较,即比较是否是同一个对象,而在其Equals的实现中,也是直接调用的==,所以对于object,它的==和equals都是进行的同一性的比较

在值类型基类ValueType,虽然是继承自object,但是它有自己的==重载以及重写了Equals方法,使其进行相等性比较,即比较内容是否一致,但它的Equals重写是通过反射实现的,速度较慢,所以当我们自定义其他值类型(如struct)时,强烈建议我们重写自己的Equals方法,而不是用基类ValueType的

PS:为什么要用反射?因为ValueType不知道我们的值类型到底有哪些字段,所以需要通过反射将所有字段取出来然后逐一进行相等性比较

三、值类型与引用类型

对于值类型,我们需要自己手动重载自己的==,如果我们不重载而直接使用==,会编译不通过,例如float、double实现中都有重载自己的==的,重载后的==是进行相等性比较,而Equals方法由于继承了ValueType的Equals方法,也是进行的相等性比较,所以我们可以不重写(但一般都会重写,原因前面已经提到了=。=),例如float、double实现中也是有重写自己的Equals方法的,同时还会定义一个参数为当前类型的Equals方法,如Double类中public bool Equals(Double obj)  和public override bool Equals(object obj)

对于引用类型string,虽然它是引用类型,但是因为它重载了自己的==,和重写了自己的Equals,所以它的Equals和==都是相等性比较

对于其他引用类型,比如我们自定义的类,因为都是隐式继承自object的,在没有重写Equals和重载==的情况下都是和object一样进行的同一性比较,但一般涉及比较接口时,我们都会在自定义的引用类型中重写我们自己的Equals和重载==

特殊的,比如一个Int或者string类型赋值给object,这时去比较==和Equals是什么情况呢?

String s1 = new String("aa");
String s2 = new String("aa");

string s3 = "bb";
string s4 = "bb";

int i1 = 1;
int i2 = 1;

object o1 = s1;
object o2 = s2;

object o3 = s3;
object o4 = s4;

object o5 = i1;
object o6 = i2;

Console.WriteLine(o1==o2)   //False
Console.WriteLine(o1.Equals(o2))  //True

Console.WriteLine(o3==o4)  //True
Console.WriteLine(o3.Equals(o4))  //True

Console.WriteLine(o5==o6)  //False
Console.WriteLine(o5.Equals(o6))  //True

如果不明白,建议详读【一、重载和重写的调用区别】

当然这里还涉及到另一个知识点:字符串常量与字符串变量的区别

字符串常量:形如我们通过string s1 = "bb"   string s2 = "bb" 这时我们的s1和s2是指向同一个地址,这是因为它的初始值是一个常量,所以其地址分配在托管堆上的静态存储区,即所谓的常量池

字符串变量:形如我们通过String s1 = new String("aa")   String s2 = new String("aa") ,这时我们的s1和s2指向的地址不一样,这是因为这是在托管堆上动态分配的地址

以上便是本人最近研究的关于c#的==和Equals的相关总结,如有不对之处,还望多多指正!

参考博文:C#中 == 与 Equals区别      C# 中 Equals 和 == 的奇怪问题

c#中==与Equals区别

上一篇:Activity的绘制流程简单分析(基于android 4.0源码进行分析)


下一篇:C++数组对象和构造函数