【问题标题】:((System.Object)p == null)((System.Object)p == null)
【发布时间】:2011-02-23 22:06:28
【问题描述】:

为什么这样做:

    // 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)?

问候,

丹

【问题讨论】:

标签: c# class struct equals


【解决方案1】:

当您不知道或不能确定原始类是否已覆盖 operator == 时,您转换为 object:

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 的真正参考检查。

【讨论】:

  • 那么,转换为 ( System.Object ) 会强制在 Object 中调用“==”吗?奇怪..
  • 在这些情况下,我总是更喜欢object.ReferenceEquals(obj, null) 语法。它更清楚地说明了代码的意图。
  • 我被拖走了;但我很想问/研究这个问题(尝试并很快改写)“当专家更正 msdn 文本时,他们是否应该详细说明?”。现在,已经加载了,但我得走了……
  • 注意:从 c# 7 开始,您可以使用“is”运算符来检查 null。 "is" 使用直接引用比较。见stackoverflow.com/questions/40676426/…
【解决方案2】:

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

【讨论】:

【解决方案3】:

更简洁的是:

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

【讨论】:

  • 如果您只是检查p 的类型是否正确,效率也会更高。
【解决方案4】:

说白了,没意义。无论类型如何,都可以始终分配 Null(除了 int 和 struct 等非可空值),因此始终可以检查它。不需要演员表

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

【讨论】:

  • 嗯,好吧。也许这就是重点,不可为空的就是。我再看一下,谢谢。如果你有时间 - msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx 问候,丹
  • @Daniel 查看我的编辑,了解为什么它不是不可为空的问题。至于你的链接。 == 运算符的重载非常奇怪。但是Equals 函数不是静态的,所以如果它没有指向一个有效的对象,那么会发生什么?这是正确的问题:)
【解决方案5】:

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

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

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

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);
  }
}

【讨论】:

    猜你喜欢
    • 2015-05-02
    • 2014-09-20
    • 2020-12-03
    • 2012-08-10
    • 2010-12-09
    • 1970-01-01
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    相关资源
    最近更新 更多