Equals、RefrenceEquals和==的区别
今天无意看到一篇有关Equals和==的区别的帖子,帖子中间简单的说成是比较引用和比较值,这样的理解很有问题。
看了看MSDN,总结如下。
从两个方面来说说这三者的区别。
先给出一个类和一个结构:
看看以下这段代码会输出何种结果
返回的结果都是 前三个比较为false,后两个为true
由结果看,静态RefrenceEquals、静态Equals、虚拟Equals和==比较的都是引用地址
而当我们换成比较Struct的时候,
静态RefrenceEquals的结果均为false,静态Equals、虚拟Equals的结果为true,false,false,false,true,==不可用在此处
由这个结果看静态Equals、虚拟Equals比较的是值
这就和我们上面得出的结果不一样了,那到底比较的是什么呢?
我们按类型来分析:
1.静态RefrenceEquals,从方法名也可以看出比较的是引用地址,在对值类型进行此比较时,始终为false,即使是RefrenceEauals(1,1),因为这里它把值首先装箱再进行比较,所以两个的引用地址是不一样的,但是RefrenceEquals(null,null)的值是true;
2.静态Equals方法,这个方法其实最终是调用了虚拟Equals方法的不同重载
3.虚拟Equals方法,可在不同类中重载,这里我们就可以理解为什么上面的两种不同类型变量的比较会有不同的结果了,比如String.Equals方法就是用于判断两个字符串的内容是否相等
一般来说,对于值类型,类型相同,并且数值相同(对于struct的每个成员都必须相同),则Equals返回true,否则返回false。而对于引用类型,默认的行为与ReferenceEquals的行为相同,仅有两个对象指向同一个Reference的时候才返回true。
静态Equals相比虚拟Equals方法有一个优点,就在于它不用考虑比较的对象是否为null;
4.==运算符,对于内置的值类型,直接判断两个对象的值是否相等,并会根据需要对对象进行类型转换,对于用户定义的值类型,比如struct,不可使用;杜宇引用类型,默认的行为与ReferenceEquals的行为相同,但是很多类对==进行了重载,比如String。
一些总结,不当之处,请指出。
看了看MSDN,总结如下。
从两个方面来说说这三者的区别。
先给出一个类和一个结构:
public class RefrenceClass
{
public int X
{get;set;}
public string Y
{get;set;}
}
public struct ValueStruct
{
public int x;
public string y;
}
1.引用类型的比较{
public int X
{get;set;}
public string Y
{get;set;}
}
public struct ValueStruct
{
public int x;
public string y;
}
看看以下这段代码会输出何种结果
RefrenceClass c1 = new RefrenceClass();
c1.X = 1;
c1.Y = "OK";
RefrenceClass c2 = new RefrenceClass();
c2.X = 1;
c2.Y = "OK";
RefrenceClass c3 = new RefrenceClass();
c3.X = 1;
c3.Y = "OK!";
RefrenceClass c4 = new RefrenceClass();
c4.X = 2;
c4.Y = "OK";
RefrenceClass c5 = new RefrenceClass();
c5=c1;
c5.X = 2;
RefrenceClass c6 = c1;
Console.WriteLine(ReferenceEquals(c1,c2).ToString());
Console.WriteLine(ReferenceEquals(c1,c3).ToString());
Console.WriteLine(ReferenceEquals(c1,c4).ToString());
Console.WriteLine(ReferenceEquals(c1,c5).ToString());
Console.WriteLine(ReferenceEquals(c1,c6).ToString());
Console.WriteLine();
Console.WriteLine(Equals(c1,c2).ToString());
Console.WriteLine(Equals(c1,c3).ToString());
Console.WriteLine(Equals(c1,c4).ToString());
Console.WriteLine(Equals(c1,c5).ToString());
Console.WriteLine(Equals(c1,c6).ToString());
Console.WriteLine();
Console.WriteLine(c1.Equals(c2).ToString());
Console.WriteLine(c1.Equals(c3).ToString());
Console.WriteLine(c1.Equals(c4).ToString());
Console.WriteLine(c1.Equals(c5).ToString());
Console.WriteLine(c1.Equals(c6).ToString());
Console.WriteLine();
Console.WriteLine(c1==c2);
Console.WriteLine(c1==c3);
Console.WriteLine(c1==c4);
Console.WriteLine(c1==c5);
Console.WriteLine(c1==c6);
Console.WriteLine();
c1,c2,c3,c4为不同的实例,c1,c5,c6是同一个引用c1.X = 1;
c1.Y = "OK";
RefrenceClass c2 = new RefrenceClass();
c2.X = 1;
c2.Y = "OK";
RefrenceClass c3 = new RefrenceClass();
c3.X = 1;
c3.Y = "OK!";
RefrenceClass c4 = new RefrenceClass();
c4.X = 2;
c4.Y = "OK";
RefrenceClass c5 = new RefrenceClass();
c5=c1;
c5.X = 2;
RefrenceClass c6 = c1;
Console.WriteLine(ReferenceEquals(c1,c2).ToString());
Console.WriteLine(ReferenceEquals(c1,c3).ToString());
Console.WriteLine(ReferenceEquals(c1,c4).ToString());
Console.WriteLine(ReferenceEquals(c1,c5).ToString());
Console.WriteLine(ReferenceEquals(c1,c6).ToString());
Console.WriteLine();
Console.WriteLine(Equals(c1,c2).ToString());
Console.WriteLine(Equals(c1,c3).ToString());
Console.WriteLine(Equals(c1,c4).ToString());
Console.WriteLine(Equals(c1,c5).ToString());
Console.WriteLine(Equals(c1,c6).ToString());
Console.WriteLine();
Console.WriteLine(c1.Equals(c2).ToString());
Console.WriteLine(c1.Equals(c3).ToString());
Console.WriteLine(c1.Equals(c4).ToString());
Console.WriteLine(c1.Equals(c5).ToString());
Console.WriteLine(c1.Equals(c6).ToString());
Console.WriteLine();
Console.WriteLine(c1==c2);
Console.WriteLine(c1==c3);
Console.WriteLine(c1==c4);
Console.WriteLine(c1==c5);
Console.WriteLine(c1==c6);
Console.WriteLine();
返回的结果都是 前三个比较为false,后两个为true
由结果看,静态RefrenceEquals、静态Equals、虚拟Equals和==比较的都是引用地址
而当我们换成比较Struct的时候,
静态RefrenceEquals的结果均为false,静态Equals、虚拟Equals的结果为true,false,false,false,true,==不可用在此处
由这个结果看静态Equals、虚拟Equals比较的是值
这就和我们上面得出的结果不一样了,那到底比较的是什么呢?
我们按类型来分析:
1.静态RefrenceEquals,从方法名也可以看出比较的是引用地址,在对值类型进行此比较时,始终为false,即使是RefrenceEauals(1,1),因为这里它把值首先装箱再进行比较,所以两个的引用地址是不一样的,但是RefrenceEquals(null,null)的值是true;
2.静态Equals方法,这个方法其实最终是调用了虚拟Equals方法的不同重载
3.虚拟Equals方法,可在不同类中重载,这里我们就可以理解为什么上面的两种不同类型变量的比较会有不同的结果了,比如String.Equals方法就是用于判断两个字符串的内容是否相等
一般来说,对于值类型,类型相同,并且数值相同(对于struct的每个成员都必须相同),则Equals返回true,否则返回false。而对于引用类型,默认的行为与ReferenceEquals的行为相同,仅有两个对象指向同一个Reference的时候才返回true。
静态Equals相比虚拟Equals方法有一个优点,就在于它不用考虑比较的对象是否为null;
4.==运算符,对于内置的值类型,直接判断两个对象的值是否相等,并会根据需要对对象进行类型转换,对于用户定义的值类型,比如struct,不可使用;杜宇引用类型,默认的行为与ReferenceEquals的行为相同,但是很多类对==进行了重载,比如String。
一些总结,不当之处,请指出。