((System.Object)p == null)

时间:2010-05-25 21:34:39

标签: c# class struct equals

为什么这样做:

    // If parameter cannot be cast to Point return false.
    TwoDPoint p = obj as TwoDPoint;
    if ((System.Object)p == null)
    {
        return false;
    }

而不是:

    // If parameter cannot be cast to Point return false.
    TwoDPoint p = obj as TwoDPoint;
    if (p == null)
    {
        return false;
    }

我不明白为什么你要写((System.Object)p)?

此致

5 个答案:

答案 0 :(得分:12)

当您不知道或无法确定原始课程是否已覆盖object时,您会投放到operator ==

using System;
class AlwaysEqual
{
    public static bool operator ==(AlwaysEqual a, AlwaysEqual b)
    {
        return true;
    }

    public static bool operator !=(AlwaysEqual a, AlwaysEqual b)
    {
        return true;
    }
}


class Program
{
    static void Main()
    {
        object o = new AlwaysEqual();
        AlwaysEqual ae = o as AlwaysEqual;

        if (ae == null)
        {
            Console.WriteLine("ae is null");
        }

        if ((object)ae == null)
        {
            Console.WriteLine("(object)ae is null");
        }
    }
}

此代码仅输出 "ae is null",显然不是这种情况。转化为object会避开AlwaysEqual类的operator ==,因此对null进行真正的参考检查。

答案 1 :(得分:1)

简单地说,这是毫无意义的。无论类型如何,都可以始终指定Null(非整数,例如整数和结构),因此可以始终检查它。演员没有必要

如果TwoDPoint是一个非可空类型,例如结构,那么它确实可能有一个点。 (System.Object)缓存会将结构有效地封装成可以为空的对象。但如果是这种情况,则obj as TwoDPoint将无效。您需要obj as TwoDPoint?才能使其可以为空。 (不能像非空格一样使用)

答案 2 :(得分:1)

.NET中的每个对象都派生自System.Object,因此不需要显式转换。

答案 3 :(得分:1)

更简洁的是:

if (!(obj is TwoDPoint)) {
  return false;
}

答案 4 :(得分:1)

如果代码在Object.Equals覆盖内,并且您不想调用相等运算符(例如,可能错误地调用Equals),则完全有意义。转换为对象允许调用标准相等运算符,它比较引用。

通常情况下,您可以使用Object.ReferenceEquals将对象的实例与null覆盖内的Equals进行比较。

例如,这会导致堆栈溢出:

public class Point {
  public override bool Equals (object other) {
    var otherPoint = other as Point;

    if (other == null)
      return false;

    //...
  }

  public static bool operator == (Point l, Point r) {
    //...
    //null checks
    if (!l.Equals(r))
      return false;
  }
}

在上面的示例中,等于运算符调用Equals并且因为otherPoint变量的类型为Point,它将调用相等运算符,从而导致无限递归。

通常,当您重写Equals并定义相等运算符时,您可以将比较逻辑放在运算符中并从Equals覆盖中调用它。请记住,如果两个都被覆盖,建议该类是不可变的。

public class Point {
  public override bool Equals (object other) {
    var otherPoint = other as Point;
    return this == otherPoint;
  }

  //must override GetHashCode() as well

  public static bool operator == (Point l, Point r) {
    if (Object.ReferenceEquals(l, null) && Object.ReferenceEquals(r, null))
      return true;
    if (Object.ReferenceEquals(l, null) || Object.ReferenceEquals(r, null))
      return false;
    //actual equality checks
  }
  public static bool operator != (Point l, Point r) {
    return !(l==r);
  }
}