¿Cuál es la diferencia entre lanzar y usar “como” en C #?

Si hay una diferencia, ¿cuál es la diferencia entre las dos formas de hacer el siguiente elenco?

En este caso, e es un objeto GridViewRowEventArgs .

 GridView gv = (GridView)e.Row.FindControl("gv"); //first way GridView gv2 = e.Row.FindControl("gv") as GridView; //second way 

Las diferencias son:

  • Si un lanzamiento falla, arroja una InvalidCastException .
  • Si el operador as falla, simplemente devuelve una referencia nula.
  • No se puede usar as con tipos de valores que no admiten nulos (p. Ej., No se puede hacer ” o as int “).
  • El operador de reparto también se usa para desempaquetar. ( as se puede usar para unbox a un tipo de valor que admite valores).
  • El operador de transmisión también puede realizar conversiones definidas por el usuario.

EDITAR: He escrito en otro lado sobre cuándo creo que es apropiado usar qué operador. Eso podría valer la pena leer …

Lo que no se menciona en las respuestas anteriores es intención : ¿por qué está realizando la conversión y (más importante) qué sucede en las líneas después de la conversión?

Por ejemplo, he visto código similar al siguiente varias veces:

if ((foo as SomeType).SomeMethod()) { /* ... */ }

Esto podría ser comparado con la versión de cast-using:

if (((SomeType) foo).SomeMethod()) { /* ... */ }

Entonces, ¿cuál de estos es mejor?

El elenco es.

El uso de as dará as resultado una NullReferenceException si la conversión falla.

Usar un elenco dará como resultado una InvalidCastException si la conversión falla.

Ahora dime, ¿cuál es una excepción más útil para la depuración? Una NullReferenceException , que podría ser producida por casi cualquier cosa, o una InvalidCastException , que le permite saber qué salió mal en realidad.

Por lo tanto, solo use as si la conversión fuera realmente opcional (lo que significa que debe haber una verificación null antes de usar la variable). De lo contrario, use un molde, lo que hace que sus intenciones sean más explícitas.

En general, la diferencia entre un elenco estático y “como”, es que el elenco emitirá una excepción si falla, mientras que “como” simplemente establecerá la variable a nulo.

La instrucción “como” básicamente intenta lanzar la variable y devuelve nulo si falla en lugar de arrojar una excepción. Como tal, el valor al que está lanzando debe ser anulable: un tipo de referencia o una primitiva que admite nulos. En tu ejemplo, tendrías que hacer:

 int? i2 = o as int; 

o no comstackrá

El reparto seguro como

 variable as type 

hace lo mismo que

 (variable is type) ? (type)variable : (type)null 

y no funcionará para los tipos de valor.

Sin embargo, si usó un tipo de referencia, digamos Table, el primero generaría InvalidCastException en caso de que o no se pueda asignar a Table y el segundo simplemente devolverá null.

Además del problema que Jon señaló, la palabra clave as arroja efectivamente o como SomeClass . Si o no se deriva de SomeClass , devuelve null . Mientras que un elenco simple lanzaría una excepción.

 SomeClass i2 = o as SomeClass; 

se convierte

 SomeClass i2; if (o is SomeClass) i2 = (SomeClass)o; else i2 = null; 

Podría estar diciendo lo obvio aquí, pero una cosa que obtienes con el ‘como’ es que tienes la garantía de que terminarás con un objeto del tipo que pediste. Esto es útil en ciertas situaciones.