1、Object.ReferenceEquals(static)
Object.ReferenceEquals
判断两个对象引用是否指向内存中的同一位置,若是使用Object.ReferenceEquals
对值类型变量进行判等,'Object.ReferenceEquals‘ 总是返回False
,需要特别注意一下。ReferenceEqual
的方法签名及方法体,如下:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool ReferenceEquals(object objA, object objB)
{
return (objA == objB);
}
从代码中可以看出传入值类型参数,会装箱成object类型,由于对象不是相同的实例,所以就会总是返回False
。
例如,
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication { class Program { static void Main(string[] args) { Object obj1 = new Object(); Object obj2 = obj1; bool areEqual = Object.ReferenceEquals(obj1, obj2); // true Console.WriteLine(areEqual); Console.WriteLine(Object.ReferenceEquals(11, 11));//false Console.ReadKey(); } } }
2、Object.Equals(static)
Object.Equals
用于比较两个对象的值或状态是否相等。可以重写 Equals 方法来定义自定义类型的相等逻辑。Object.Equals
的方法签名及方法体,如下:
public static bool Equals(object objA, object objB)
{
return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
}
例如,
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication { class Program { static void Main(string[] args) { int a = 10; int b = 10; bool areEqual = Object.Equals(a, b); // true Console.WriteLine(areEqual); object obj1 = new object(); object obj2 = new object(); areEqual = Object.Equals(obj1, obj2); // 返回 false,因为 obj1 和 obj2 指向不同的对象 Console.WriteLine(areEqual); Console.ReadKey(); } } }
3、Operator操作符(==)
==
运算符可以用于比较对象。对于引用类型,默认行为是比较引用,但可以重载这些运算符来实现自定义的值比较。如下代码:
//添加下面代码到ThreeDPoint类定义之前 public static bool operator ==(ThreeDPoint a, ThreeDPoint b) { // If both are null, or both are same instance, return true. if (System.Object.ReferenceEquals(a, b)) { return true; } // If one is null, but not both, return false. if (((object)a == null) || ((object)b == null)) { return false; } // Return true if the fields match: return a.x == b.x && a.y == b.y && a.z == b.z; } public static bool operator !=(ThreeDPoint a, ThreeDPoint b) { return !(a == b); }
需要注意的是,运算符 ==
的重写中的常见错误是,重写的方法内还使用 (a == b)、(a == null) 或 (b == null) 来检查引用相等性。这会调用重载的运算符 ==
,从而导致无限循环。应使用 ReferenceEquals
或将类型强制转换为 Object
来避免无限循环。
4、Instance.Equals
实例对象的Equals
方法,这个其实和第二种Object.Equals(static)
类似,只是参数只有一个,但是这个方法是在class
内部继承Object
的,是可以进行重写的。CLR会要求所有的类型都派生自Object
,每个class
内部都可以重写这个方法,如下:
public class Point { public int X { get; set; } public int Y { get; set; } public override bool Equals(object obj) { if (obj == null || GetType() != obj.GetType()) return false; Point p = (Point)obj; return (X == p.X) && (Y == p.Y); } public override int GetHashCode() { return X ^ Y; } }