((System.Object) p == ноль) - PullRequest
5 голосов
/ 26 мая 2010

Зачем это делать:

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

С уважением,

Dan

Ответы [ 5 ]

12 голосов
/ 26 мая 2010

Вы приводите к 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 позволяет избежать operator == класса AlwaysEqual и, следовательно, является истинной проверкой на соответствие null.

1 голос
/ 26 мая 2010

Имеет смысл, если этот код находится внутри 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);
  }
}
1 голос
/ 26 мая 2010

Каждый объект в .NET является производным от System.Object, поэтому нет необходимости явно приводить.

1 голос
/ 26 мая 2010

И еще более кратким будет:

if (!(obj is TwoDPoint)) {
  return false;
}
1 голос
/ 26 мая 2010

Проще говоря, это бессмысленно. Нулевое значение всегда может быть назначено (за исключением ненулевых значений, таких как целые и структуры) независимо от типа, поэтому его всегда можно проверить. В ролях нет необходимости

Если TwoDPoint является ненулевым типом, таким как структура, тогда действительно он может иметь точку. Кэш (System.Object) будет эффективно упаковывать структуру в обнуляемый объект. Но если бы это было так, то obj as TwoDPoint не будет действительным. Вам понадобится obj as TwoDPoint?, чтобы сделать его обнуляемым. (нельзя использовать как с ненулевыми значениями)

...