值类型变量判断就是比较值是否相等,而引用类型的对象判断是否相等,一般是判断指定的对象是否是相同的实例。也就是比较对象引用的值,但是也有可能有特殊情况,虽然不是相同的实例,但在业务上可能是相等的。就要结合具体的情况判断是否相等了。一般判断对象是否相等的方法有4种。

1、Object.ReferenceEquals(static):确定指定的 Object 实例是否是相同的实例,值得注意的是使用Object.ReferenceEquals对值类型变量进行判等,'Object.ReferenceEquals‘ 总是返回False。ReferenceEqual的方法签名及方法体,如下:

 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  public static bool ReferenceEquals(object objA, object objB)
  {
      return (objA == objB);
  }

通过代码可以看出,代码中还是调用Operator==,那我们一般调用Operator==是可以判断值类型量否相等的,相信大家都会有这个疑问,那是因为方法参数是object类型,传入值类型参数,会装箱成object类型,对象就不是相同的实例,这样就会总是返回False了,

2、Object.Equals(static):确定指定的对象是否等于当前对象,这个方法不仅可以判断引用类型,也可以判断值类型是否相等,通过.NET Reflector可以看到Object.Equals的方法签名及方法体,如下:

 public static bool Equals(object objA, object objB)
 {
     return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
 }

3、Operator操作符(==):默认情况下,Operator==在对引用类型对象判等的本质和Object.ReferenceEquals是相同的即确定指定的变量是否是相同的实例。Object.ReferenceEquals和Object.Equals也用了双等号。判断值类型就是比较值是否相等。我们也可以重写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 override bool Equals(object obj)
{
    ThreeDPoint p=obj as ThreeDPoint;
    if(p != null)
        return p.x == this.x && p.y == this.y && p.z == this.z;
    return false;
}