比较对象的相等性
在所有类型的基类中(System.Object)定义三个不同的方法,用于比较对象的相等性。下面我们分别来看看这三个方法:
一、静态方法ReferenceEquals()
从名字我就很容易看出来,这是用于比较两个对象是否具有相同的引用。因此这个方法对于值类型是没有任何意义的。因为值类型转换成引用类型有一个装箱的过程,每次都会得到不同的应用。所以对于值类型这个方法的返回值永远是false。
二、静态方法Equals()
这个方法和虚拟的实例方法作用相同。不同在于它处理了null的情况。如果两个参数都是null,则返回true,如果有一个为null则返回false。如果两个参数都不为null,则调用实例的Equals方法。因此如果对一个对象重写的实例的Equals方法,实际上也重写了该静态方法。
三、虚拟方法Equals()
这个方法在System.Object里面实现也是比较引用,因为虚拟方法,所以我们可以在自己定义的类中重写这个方法,从而达到比较值的目的。
下面我们来看个例子验证一下:
先定义一个类,并重写虚拟的Equals()方法,让它比较值,并调用基类的MemberwiseClone()方法实现浅度赋值。
public class Document { public Document(string name, int size) { this.Name = name; this.Size = size; this.Content = ""; } public string Name { get; set; } public int Size { get; set; } public string Content { get; set; } public Document Clone() { return MemberwiseClone() as Document; } public override bool Equals(object obj) { if (base.Equals(obj)) return true; Document doc = obj as Document; return Name == doc.Name && Size == doc.Size && Content == doc.Content; } }
下面分别调用三个比较方法:
static void Main(string[] args) { Document doc1 = new Document("doc", 100); Document doc2 = doc1.Clone(); Console.WriteLine("object.ReferenceEquals(doc1, doc2):{0}", object.ReferenceEquals(doc1, doc2)); Console.WriteLine("object.Equals(doc1, doc2):{0}", object.Equals(doc1, doc2)); Console.WriteLine("doc1.Equals(doc2):{0}", doc1.Equals(doc2)); int x1 = 1; int y1 = 1; Console.WriteLine("object.ReferenceEquals(x1, y1):{0}", object.ReferenceEquals(x1, y1)); Console.WriteLine("object.Equals(x1, y1):{0}", object.Equals(x1, y1)); Console.WriteLine(" x1.Equals(y1):{0}", x1.Equals(y1)); Console.ReadLine(); }
运行得到下面的结构:
object.ReferenceEquals(doc1, doc2):False object.Equals(doc1, doc2):True doc1.Equals(doc2):True object.ReferenceEquals(x1, y1):False object.Equals(x1, y1):True x1.Equals(y1):True
可以看到,重写了Equals方法,静态方法也返回了true。同样对于值类型静态的Equals方法和虚拟的Equals方法也都返回了true,这是因为在System.ValueType中重写了Equals方法,实现了值的比较。