Casting: (NewType) vs. Object as NewType

Possibile duplicato:
Casting vs usando la parola chiave ‘as’ nel CLR

Qual è in realtà la differenza tra questi due calchi?

SomeClass sc = (SomeClass)SomeObject; SomeClass sc2 = SomeObject as SomeClass; 

Normalmente, dovrebbero essere entrambi cast espliciti per il tipo specificato?

Il primo genererà un’eccezione se il tipo di sorgente non può essere trasmesso al tipo di destinazione. Quest’ultimo risulterà in sc2 come riferimento nullo, ma senza eccezioni.

[Modificare]

La mia risposta originale è certamente la differenza più pronunciata, ma come sottolinea Eric Lippert, non è l’unico. Altre differenze includono:

  • Non è ansible utilizzare l’operatore ‘as’ per eseguire il cast su un tipo che non accetta ‘null’ come valore
  • Non puoi usare ‘as’ per convertire le cose, come i numeri in una diversa rappresentazione (float in int, per esempio).

E infine, usando ‘as’ come l’operatore del cast, stai anche dicendo “Non sono sicuro che questo avrà successo”.

Si noti inoltre che è ansible utilizzare solo la parola chiave as con un tipo di riferimento o un tipo nullable

vale a dire:

 double d = 5.34; int i = d as int; 

non verrà compilato

 double d = 5.34; int i = (int)d; 

compilerà.

Il typecasting utilizzando “as” è ovviamente molto più veloce quando il cast fallisce, poiché evita le spese di lancio di un’eccezione.

Ma non è più veloce quando il cast ha successo. Il grafico su http://www.codeproject.com/KB/cs/csharpcasts.aspx è fuorviante perché non spiega cosa sta misurando.

La linea di fondo è:

  • Se ti aspetti che il cast abbia successo (cioè un fallimento sarebbe eccezionale), usa un cast.

  • Se non sai se ci riuscirà, usa l’operatore “as” e verifica il risultato per null.

Una differenza tra i due approcci è che il primo ((SomeClass) obj) può causare la chiamata di un convertitore di tipi .

Ecco un buon modo per ricordare il processo che ognuno di loro segue che io uso quando cerco di decidere quale è meglio per la mia circostanza.

 DateTime i = (DateTime)value; // is like doing DateTime i = value is DateTime ? value as DateTime : throw new Exception(...); 

e il prossimo dovrebbe essere facile da indovinare cosa fa

 DateTime i = value as DateTime; 

nel primo caso se il valore non può essere lanciato di un’eccezione viene lanciata nel secondo caso se il valore non può essere lanciato, i è impostato su null.

Quindi nel primo caso viene eseguito un arresto hard se il cast fallisce nel secondo cast viene eseguito un arresto soft e si potrebbe riscontrare una NullReferenceException in seguito.

Bene, l’operatore “as” “aiuta” a seppellire il tuo problema in modo molto più basso perché quando viene fornita un’istanza incompatibile restituirà null, forse lo passerai a un metodo che lo passerà a un altro e così via e infine tu ” Otterrai una NullReferenceException che renderà più difficile il tuo debugging.

Non abusarne. L’operatore di cast diretto è migliore nel 99% dei casi.

Per espandere il commento di Rytmis , non è ansible utilizzare la parola chiave as per le strutture (Tipi di valore), poiché non hanno valore nullo.

Tutto ciò si applica ai tipi di riferimento, i tipi di valore non possono utilizzare la parola chiave as in quanto non possono essere nulli.

 //if I know that SomeObject is an instance of SomeClass SomeClass sc = (SomeClass) someObject; //if SomeObject *might* be SomeClass SomeClass sc2 = someObject as SomeClass; 

La syntax del cast è più veloce, ma solo quando ha successo, è molto più lento fallire.

La migliore pratica è quella da utilizzare as quando non si conosce il tipo:

 //we need to know what someObject is SomeClass sc; SomeOtherClass soc; //use as to find the right type if( ( sc = someObject as SomeClass ) != null ) { //do something with sc } else if ( ( soc = someObject as SomeOtherClass ) != null ) { //do something with soc } 

Tuttavia, se sei assolutamente sicuro che someObject è un’istanza di SomeClass usa cast.

In .Net 2 o versioni successive di generics significa che molto raramente è necessario disporre di un’istanza non tipizzata di una class di riferimento, quindi quest’ultima viene utilizzata meno frequentemente.

Il cast parentetico lancia un’eccezione se il tentativo di lancio fallisce. Il cast “as” restituisce null se il tentativo di lancio fallisce.

Faranno diverse eccezioni.
(): NullReferenceException
come: InvalidCastException
Quale potrebbe aiutare per il debug.

La parola chiave “as” tenta di eseguire il cast dell’object e se il cast fallisce, null viene restituito in silenzio. L’operatore di cast () lancia immediatamente un’eccezione se il cast fallisce.

“Usa solo il C #” come “parola chiave in cui ti aspetti che il cast fallisca in un caso non eccezionale.Se stai contando su un cast per avere successo e sono impreparati a ricevere qualsiasi object che fallirebbe, dovresti usare il () cast operatore in modo che venga lanciata un’eccezione appropriata e utile. ”

Per esempi di codice e un’ulteriore spiegazione: http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html

È come la differenza tra Parse e TryParse. Usi TryParse quando pensi che potrebbe fallire, ma quando hai la certezza che non fallirà, usi Parse.

Per quelli di voi con esperienza VB.NET, (tipo) è lo stesso di DirectCast e “come tipo” è lo stesso di TryCast.

E per completezza, Eric Lippert ha un post sul blog sulla differenza e alcuni avvertimenti.