Domanda

Possibile duplicato:
Casting e utilizzo della parola chiave "as" nel CLR

Qual è effettivamente la differenza tra questi due cast?

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

Normalmente, dovrebbero essere entrambi cast espliciti del tipo specificato?

È stato utile?

Soluzione

Il primo genererà un'eccezione se non è possibile eseguire il cast del tipo di origine sul tipo di destinazione.Quest'ultimo comporterà che sc2 sia un riferimento nullo, ma nessuna eccezione.

[Modificare]

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

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

E infine, usando 'as' vs.l'operatore del cast, stai anche dicendo "Non sono sicuro che avrà successo".

Altri suggerimenti

Tieni inoltre presente che puoi utilizzare la parola chiave as solo con un tipo di riferimento o un tipo nullable

cioè:

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 la spesa di generare un'eccezione.

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

La conclusione è:

  • Se ti aspetti che il cast abbia successo (ad es.un fallimento sarebbe eccezionale), utilizzare un cast.

  • Se non sai se avrà successo, usa l'operatore "as" e verifica che il risultato sia nullo.

Una differenza tra i due approcci è che il primo ((SomeClass)obj) può causare a convertitore di tipo da chiamare.

Ecco un buon modo per ricordare il processo seguito da ciascuno di essi e che utilizzo quando cerco di decidere quale è meglio per le mie circostanze.

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

e il prossimo dovrebbe essere facile indovinare cosa fa

DateTime i = value as DateTime;

nel primo caso se il valore non può essere castato viene lanciata un'eccezione, nel secondo caso se il valore non può essere castato, i viene impostato su null.

Pertanto, nel primo caso viene effettuato un arresto definitivo se il cast fallisce, nel secondo viene effettuato un arresto graduale e potresti riscontrare una NullReferenceException in seguito.

BENE l'operatore "as" ti "aiuta" a seppellire il tuo problema molto più in 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 otterrai una NullReferenceException che renderà più difficile il debug.

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

Per espandere Il commento di Rytmis, non puoi usare il file COME parola chiave per strutture (tipi di valore), poiché non hanno valore null.

Tutto ciò si applica ai tipi di riferimento, i tipi di valore non possono utilizzare il file as parola chiave poiché 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 sintassi del cast è più veloce, ma solo in caso di successo è molto più lento fallire.

La migliore pratica è usare as quando non conosci 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 ne sei assolutamente sicuro someObject è un'istanza di SomeClass quindi usa cast.

In .Net 2 o versioni successive i generici significano che molto raramente è necessario avere un'istanza non tipizzata di una classe di riferimento, quindi quest'ultima viene utilizzata meno spesso.

Il cast tra parentesi genera un'eccezione se il tentativo di cast fallisce.Il cast "as" restituisce null se il tentativo di cast fallisce.

Lanceranno diverse eccezioni.
() :NullReferenceException
COME :InvalidCastException
Il che potrebbe aiutare per il debug.

La parola chiave "as" tenta di eseguire il cast dell'oggetto e se il cast fallisce, null viene restituito silenziosamente.L'operatore cast () genererà immediatamente un'eccezione se il cast fallisce.

"Utilizzare la parola chiave C# "as" solo quando si prevede che il cast fallisca in un caso non eccezionale.Se contate sulla riuscita di un cast e non siete preparati a ricevere qualsiasi oggetto che fallirebbe, dovreste utilizzare l'operatore cast () in modo che venga lanciata un'eccezione appropriata e utile."

Per esempi di codice e ulteriori spiegazioni: http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html

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

Per quelli di voi con esperienza VB.NET, (tipo) è uguale a DirectCast e "come tipo" è uguale a TryCast.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top