C#:引用类型和值类型的相等比较

  1. 引用类型的相等比较

System.Object定义了3个不同的方法来比较对象的相等性:ReferenceEquals()和Equals()的两个版本。再加上比较运算符,实际上有4种进行相等比较的方式。

  • ReferenceEquals()方法
public static bool ReferenceEquals(object objA, object objB)

ReferenceEquals()是一个静态方法,测试两个引用是否指向类的同一个实例,即两个引用是否包含内存中的相同地址。作为静态方法,它不能重写,所以只能使用System.Object的实现代码。如果提供的两个引用指向同一个对象实例,ReferenceEqualsa()总是返回true,否则就返回false,但是它认为null等于null。

1 SomeClass x, y;
2 x = new SomeClass();
3 y = new SomeClass();
4 bool B1 = ReferenceEquals(null, null);   //return true
5 bool B2 = ReferenceEquals(null, x);      //return false
6 bool B3 = ReferenceEquals(x, y);         //return false because x and y point to different objects
  • 虚拟的Equals()方法
public virtual bool Equals(object obj)

返回一个值,该值指示当前的Object是否等于当前的Object
Equals的默认实现仅支持引用相等,但派生类可重写此方法以支持值相等

在下面的列表中,x,y,z表示不为空引用:

(1)除涉及浮点型的情况外,x.Equals(x)都返回true

(2)x.Equals(y)返回与y.Equals(x)相同的值

(3)如果x和y都为NaN,则x.Equals(y)返回true

(4)当且仅当x.Equals(z)返回true时,(x.Equals(y)&&y.Equals(z))才返回相同的值

(5)只要不修改x和y引用的对象,对x.Equals(y)的相继调用将返回相同的值

(6)x.Equals(null)返回false

 

 1 using System;
 2 
 3 public class Sample {
 4     void Method() {
 5     Object Obj1 = new Object();
 6     Object Obj2 = new Object();
 7     Console.WriteLine(Obj1.Equals(Obj2)); //===> false
 8     Obj2 = Obj1;
 9     Console.WriteLine(Obj1.Equals(Obj2)); //===> true
10     }
11 }

 

  • 静态的Equals()方法
public static bool Equals(object objA, object objB)

如果objA是与objB相同的实例,或者如果两者均为空引用,或者如果objA.Equals(objB)返回true,则为true,否则为false

 

  2. 值类型的相等比较

在进行值类型的相等比较时,采用与引用类型相同的规则:ReferenceEquals()用于比较引用,Equals()用于比较值。最大的区别是,值类型需要装箱才能把它们转换为引用,才能对它们执行方法。

ReferenceEquals()在应用值类型时,总是返回false,因为为了调用这个方法,值类型需要装箱到对象中。即使使用下面的代码:

bool b = ReferenceEquals(v, v);          //v is a variable of some value type

也会返回false,因为在转换每个参数时,v都会被单独装箱。

   3. 比较运算符比较

==运算符用于比较两个操作数是否相对。对于基本数据类型,就不用多说了,没有太大问题

对于引用数据类型,如类对象、string,可能就有一点疑惑
 
1 string s1="test";
2 string s2=string.copy(s1);
3 Console.WriteLine(s1==s2);      //===>true
4 Console.WriteLine((object)s1==(object)s2);     //===>false
 
稍微修改一下
1 string s1="test";
2 string s2=s1;
3 或string s2="test";
4 Console.WriteLine(s1==s2);      //===>true
5 Console.WriteLine((object)s1==(object)s2);     //===>true
可能对于string类型常量,是保存在堆栈中的,然后string类型对象就引用同一个对象
而用string.copy()方法,会在堆栈中产生一个新的string对象
 
对于==操作符:
如果两个基本数据类型的操作数,它们的数值相等,它们就被认为是相等的
如果两个object类型的表达式都指向相同的对象或者都是空,它们被认为是相等的
如果字符串实例有相同的长度并且在每个字符的位置都相同或者都为空,它们被认为是相等的
posted @ 2016-03-16 14:35  腾冲  阅读(2494)  评论(0编辑  收藏  举报