C# Object Equals 简介1:
本篇只讲解,除String类型以外的Equals 比较,因为String类型比较特别,固决定新开一篇文章单独介绍。
首先在此声明,除非有一定的内存知识基础,否则你可以直接跳到尾部看两个考点的总结即可,然后在之后的工作中慢慢体会吧。
先说几个专业名词:
栈:缓存,类似与电脑内存条,4G,8G,16G,
堆:类似于本地固态硬盘
值类型:int,float,double…分配内存于栈中
引用类型:string,object…分配内存于堆中
点击此处→了解堆栈
不论你是什么类型,终究不过是值类型和引用类型比较。
考点1 :Object.Equals(A,B) 与 A.Equals(B) 区别
注:看下面代码之前首先要明白A.Equals()是 A继承Object这个类的内部方法(在不重写的情况下) 。而 Object.Equals()是Object类的静态方法, 大家如果感兴趣就去看看CLR里这个方法是怎么实现的,其实实现的代码都一样。
Object A = null;
Object B = null;
List list = null;
Console.WriteLine("result:" + Object.Equals(A, B));
Console.WriteLine("result:" + Object.Equals(A, list ));
Console.WriteLine("result:" + A.Equals(B));
运行以上代码,结果:
- result:true
原因:NULL也相当于一块内存地址。A,B在栈里所存的引用地址,是指向同一块内存NULL,所以A=B。 - result:true
原因: 同理,别看A与list类型不一样,但是所指向的内存地址是同一个。 - 报错
原因:,这里也是变向的考验了你有没有好的编程习惯,所以以后在用到Equals方法时,要用第一种写法,避免空指针异常。
那么这种情况难道就无法挽回了吗?其实是可以的:
String A = null;
String B = null;
List list = null;
bool flag = A == null ? B == null : A.Equals(B);
Console.WriteLine("result:" + flag);
Console.WriteLine("result:" + Object.Equals(A, B));
Console.WriteLine("result:" + Object.Equals(A, list));
运行以上代码,结果:
1.result:true
2.result:true
3.result:true
总结:只要不是出现A的对象是Null的情况,Object.Equals(A,B) 与 A.Equals(B) 并没有区别;而如果你执意用A.Equals(B)也可以,不嫌麻烦就像上面这么写吧。
考点2 :A==B 与 object.ReferenceEquals(A,B) 区别
int A = 1;
int B = 1;
Console.WriteLine("result:" + (A == B));
Console.WriteLine("result:" + (1 == 1));
Console.WriteLine("result:" + (1 == A));
Console.WriteLine("result:" + (object.ReferenceEquals(A, B)));
Console.WriteLine("result:" + (object.ReferenceEquals(1, 1)));
Console.WriteLine("result:" + (object.ReferenceEquals(1, A)));
运行以上代码,结果:
1.result:true 原因:值类型与值类型比较
2.result:true 原因:与1相同
3.result:true 原因:与1相同
4.result:false 原因:值类型被装箱,相当于new一个堆内存
5.result:false 原因:与4相同
6.result:false 原因:与4相同
总结:
==:只有值类型与值类型比较才相等。
object.ReferenceEquals:参数是引用类型,比较的是参数的地址,如果参数不是引用类型,就强转成引用类型,相当于在堆里开辟了一块新的内存空间。