2010-05-25 15 views
5

Perché fare questo:((System.Object) p == null)

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

Invece di questo:

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

Non capisco perché ci si mai scritto ((Sistema .Object) p)?

saluti,

Dan

+1

Non è necessario. – ChrisF

+1

Sto aspettando che lui dica questo è come il suo insegnante ha detto di farlo o qualcosa :) – Earlz

+3

Okay ma ... http://msdn.microsoft.com/en-us/library/ms173147(VS.80) .aspx –

risposta

12

lanci per object quando non si conosce o non si può essere sicuri che la classe originale ha ignorato 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"); 
     } 
    } 
} 

Questo codice uscite solo"ae is null", che ovviamente non è il caso. Il cast a object evita la classe della classe operator == ed è pertanto un vero controllo di riferimento rispetto a null.

+0

Quindi, trasmettere a (System.Object) forzerebbe l'invocazione di "==" in Object? Strano .. – OscarRyz

+5

Preferisco sempre la sintassi 'object.ReferenceEquals (obj, null)' in queste situazioni. Spiega l'intenzione del codice molto più chiaramente. – LukeH

+0

Sono trascinato via; ma mi piacerebbe chiedere/ricercare la domanda (prova a riformulare a breve) "quando un esperto corregge il testo di msdn dovrebbero elaborarne altri?". Ora, è carico ma devo andare ... –

1

Chiaramente parlando, è inutile. Null può sempre essere assegnato (eccetto per valori non nullable come int e structs) indipendentemente dal tipo, quindi può sempre essere controllato. Il cast non è necessario

Se TwoDPoint è un tipo non annullabile come una struttura, in effetti potrebbe avere un punto. La cache (System.Object) potrebbe effettivamente trasformare la struttura in un oggetto nullable. Ma se così fosse, allora obj as TwoDPoint non sarebbe valido. Avresti bisogno di obj as TwoDPoint? per renderlo nullable. (non può essere utilizzato come con valori non nulli)

+0

Hmm ok. Forse è questo il punto, il non nullable che è. Lo guarderò un po 'di più, grazie. Se si ha il tempo - http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx Cordiali saluti, Dan –

+0

@Daniel vedere la mia modifica per il motivo per cui non è un non- problema nullable. Per quanto riguarda il tuo link però. È piuttosto curioso l'overloading dell'operatore '=='. ma la funzione 'Equals' non è statica, quindi se non punta ad un oggetto valido allora cosa succede? Questa è la domanda corretta :) – Earlz

+0

@Daniel Penso che @Mark sia corretto su questo. – Earlz

1

Ogni oggetto in .NET è derivato da System.Object quindi non è necessario il cast esplicito.

+0

Cool - sì, mi ci è voluto un po '; hai ragione, vedo. Grazie. Il msdn http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx mi ha confuso. Scusate. –

1

E ancora più conciso sarebbe:

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

Sarebbe anche più efficiente se stai solo controllando che 'p' sia del tipo giusto. – ChrisF

1

Ha senso se il codice è all'interno della sostituzione Object.Equals e non si desidera richiamare l'operatore di uguaglianza (che potrebbe, ad esempio, chiamare erroneamente Equals). La trasmissione su oggetto consente di chiamare l'operatore di uguaglianza standard, che confronta i riferimenti.

Normalmente, è necessario utilizzare Object.ReferenceEquals per confrontare un'istanza di un oggetto su null all'interno di override Equals.

Ad esempio, questo potrebbe causare uno stack overflow:

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

In precedenza operatore esempio uguaglianza chiamate Equals e perché otherPoint variabile è di tipo Point, sarebbe invocare l'operatore di uguaglianza, causando ricorsione infinita.

Normalmente, quando si esegue l'override di Equals e si definisce l'operatore di uguaglianza, si inserisce la logica di confronto nell'operatore e si richiama quella dall'override Equals. Tieni presente che è consigliabile che la classe sia immutabile se entrambe vengono sovrascritte.

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