2010-05-25 2 views
5

Почему это:((System.Object) р == NULL)

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

С уважением,

Dan

+1

Вам не нужно. – ChrisF

+1

Я жду его, чтобы сказать, что это его учитель сказал, чтобы сделать это или что-то такое :) – Earlz

+3

Хорошо, но ... http://msdn.microsoft.com/en-us/library/ms173147(VS.80) .aspx –

ответ

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

+0

Итак, приведение к (System.Object) приведет к вызову «==» в Object? Strange .. – OscarRyz

+5

Я всегда предпочитаю синтаксис 'object.ReferenceEquals (obj, null)' в этих ситуациях. В нем четко указано намерение кода. – LukeH

+0

Меня оттаскивают; но я бы хотел спросить/исследовать вопрос (вкратце перефразируйте), «когда эксперт исправляет текст msdn, если они уточнят больше?». Теперь, это загружено, но я должен идти ... –

1

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

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

+0

Хм хорошо. Возможно, в этом и состоит суть, не имеющая значения. Я посмотрю на это немного больше, спасибо. Если у вас есть время - http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx С уважением, Dan –

+0

@ Даниэль см. Мое редактирование, почему он не является не- nullable проблема. Что касается вашей ссылки. Это довольно любопытно перегрузка оператора '=='. но функция 'Equals' не является статической, поэтому, если она не указывает на действительный объект, то что происходит? Это правильный вопрос :) – Earlz

+0

@ Даниэль Я думаю, что @Mark верен на этом. – Earlz

1

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

+0

Прохладный - да, взял меня некоторое время; вы правы, я вижу. Благодарю. Msdn http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx смутил меня. Сожалею. –

1

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

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

Было бы также более эффективно, если бы вы просто проверяли, что 'p' имеет правильный тип. – ChrisF

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