2012-04-16 12 views
6

Eventuali duplicati:
Why check this != null?Perché String.Equals (Object obj) controlla se questo == null?

// Determines whether two strings match. 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
public override bool Equals(Object obj) 
{ 
    //this is necessary to guard against reverse-pinvokes and 
    //other callers who do not use the callvirt instruction 
    if (this == null) 
     throw new NullReferenceException(); 

    String str = obj as String; 
    if (str == null) 
     return false; 

    if (Object.ReferenceEquals(this, obj)) 
     return true; 

    return EqualsHelper(this, str); 
} 

La parte che non capisco è il fatto che si sta controllando per l'istanza corrente, this, contro il nulla. Il commento è un po 'confuso, quindi mi chiedevo cosa significasse realmente quel commento?

Qualcuno può dare un esempio di come questo potrebbe interrompersi se quell'assegno non fosse presente, e questo significa che dovrei anche inserire tale controllo nelle mie classi?

+0

@FlorianGreinacher: non un possibile duplicato, ma praticamente un duplicato esatto, lol. Mi chiedo perché non è comparso in "Related" quando stavo scrivendo la mia domanda? –

risposta

6

Questo controllo è presente come protezione contro il codice nativo che può richiamare la funzione con un puntatore nullo this. Questo non può accadere in C#, quindi non devi mettere guardie simili nel tuo codice. È possibile che la classe String sia stata scritta prima che C# sia stato finalizzato e che l'autore possa aver pensato che fosse importante proteggerli da zero, o forse è solo normale chiamare i metodi String dal codice nativo e altri luoghi che rendono facile chiamare metodi su null .

Si noti che anche se si riesce a chiamare con un numero this nullo e non si dispone della protezione, tutto ciò che accadrà è che l'eccezione sarà leggermente diversa. Potrebbe essere un'eccezione diversa e potrebbe essere lanciata da un membro diverso, ma altrimenti è improbabile che faccia la differenza.

In altre parole, se il controllo Null non era presente, lo EqualsHelper (o uno dei suoi messaggi di risposta) genererebbe l'eccezione anziché Equals. Dato che è desiderabile nascondere gli interni della funzione visibile all'utente, ha senso mettere il controllo all'inizio.

2
  • Lingue come C# e VB.NET utilizzano callvirt per lanciare NullReference prima che venga immesso un metodo di istanza (questo == null) i controlli non sono necessari.
  • Lingue come F # e Managed C++ (la maggior parte delle volte) utilizzano l'istruzione di chiamata in cui è possibile accedere a un metodo di istanza con un puntatore null. (questo == null) ha un effetto.

Il controllo nullo aggiunto non si riferisce solo a questi ultimi linguaggi, ma aiuta anche la debugabilità a gettare nel punto in cui si verifica l'errore (chiamare un metodo di istanza di un oggetto nullo). Se non ci fosse, puoi chiamare qualsiasi metodo all'interno della classe senza errori, purché questo non sia mai dereferenze (accede alle variabili membro). Questo può andare così lontano che sul tuo oggetto nullo hanno funzionato diverse chiamate al metodo e all'improvviso si ottiene di nuovo un'eccezione di riferimento null (il metodo in cui è stato effettuato l'accesso ai dati di istanza).

Se si osservano i controlli all'interno delle classi .NET, è chiaro che solo su alcune classi importanti come le string contengono tali protezioni. Altri metodi come IndexOf non si guardano da questo. Ciò è incoerente, ma ritengo che la penalizzazione delle prestazioni per tali doppi controlli null non valga la pena perché la maggior parte degli utenti del BCL sono lingue che usano l'istruzione callvirt in cui un secondo controllo nullo non aiuta.

+1

In F #, 'let x =" a ".Uguali ("b") 'compila ancora a' callvirt' – colinfang

Problemi correlati