2015-09-26 11 views
5

sto guardando l'articolo da MSDN Guidelines for Overloading Equals() and Operator ==Strano cast Equals variazione fornita da MSDN

e ho visto il seguente codice

public override bool Equals(object obj) 
{ 
    // If parameter is null return false. 
    if (obj == null) 
    { 
     return false; 
    } 

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

    // Return true if the fields match: 
    return (x == p.x) && (y == p.y); 
} 

la cosa strana è il cast di opporsi nel secondo caso

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

Perché p viene nuovamente assegnato all'oggetto? Non è abbastanza per scrivere questa

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

Se p non può essere colato a TwoDPoint, allora il suo valore sarà nullo. Sono sconcertato, probabilmente non capisco qualcosa di banale ...

EDIT

più Uno di questi cast è presentato in un altro metodo Equals

public bool Equals(TwoDPoint p) 
{ 
    // If parameter is null return false: 
    if ((object)p == null) 
    { 
     return false; 
    } 
} 

Anche in questo caso è sufficiente controllare solo if(p == null)

+1

Questo è un odore di codice. Dovrebbero aver usato ReferenceEquals. – usr

risposta

7

(object)p == null utilizza l'operatore integrato == che in questo caso verifica l'uguaglianza di riferimento. p == null chiamerebbe un sovraccarico operator== per il tipo specificato. Se il sovraccarico operator== sarà implementato in termini di Equals (non lo è, nell'esempio a cui ci si collega), si avrà una ricorsione infinita. Anche se non è implementato in termini di Equals, farebbe ancora di più del necessario.

2

Questo per garantire che l'operatore == chiamato sia l'implementazione predefinita da Object, non quella definita dall'utente. È un errore comune introdurre la ricorsione illimitata nel codice come se facessero chiamare i propri operatori.

4

Solo per completare entrambe le risposte, la documentazione visualizzata non è aggiornata come indicato nella parte superiore della pagina. Se si guarda al newer guidelines, c'è una nota che spiega esattamente il motivo per cui è stato fatto:

Un errore comune in overload di operatore == è quello di utilizzare (a == b), (a == null), o (b == null) per verificare l'uguaglianza di riferimento. Questo invece crea una chiamata all'operatore sovraccarico ==, causando un ciclo infinito . Utilizzare ReferenceEquals o eseguire il cast del tipo su Object, per evitare il ciclo .

Fondamentalmente, così facendo è uguale all'utilizzo object.ReferenceEquals, che è ciò che il codice è in realtà cercando di fare:

TwoDPoint p = obj as TwoDPoint; 
if (object.ReferenceEquals(p, null)) 
{ 
    return false; 
} 
Problemi correlati