type operator objetos convert cast another c# casting

operator - C#"como" elenco vs elenco clásico



casting de objetos en c# (10)

Posible duplicado:
Casting vs usando la palabra clave ''como'' en el CLR

Recientemente aprendí sobre una forma diferente de lanzar. En lugar de usar

SomeClass someObject = (SomeClass) obj;

uno puede usar esta sintaxis:

SomeClass someObject = obj as SomeClass;

que parece devolver nulo si obj no es SomeClass, en lugar de arrojar una excepción de lanzamiento de clase.

Veo que esto puede llevar a una NullReferenceException si el lanzamiento falla y trato de acceder a la variable someObject. Entonces me pregunto ¿cuál es la razón detrás de este método? ¿Por qué debería uno usar esta forma de conversión en lugar de la (antigua), sino que parece mover el problema de un lanzamiento fallido "más profundamente" al código?


Con el método "clásico", si el lanzamiento falla, se lanza una excepción. Con el método como, da como resultado nulo, que se puede verificar y evitar que se produzca una excepción.

Además, solo puede usar "como" con los tipos de referencia, por lo que si va a encasillar a un tipo de valor, igual debe usar el método "clásico".

Nota:

El método as solo se puede usar para tipos a los que se les puede asignar un valor null . Ese uso solo significa tipos de referencia, pero cuando salió .NET 2.0, introdujo el concepto de un tipo de valor que admite valores. Como a estos tipos se les puede asignar un valor null , son válidos para usar con el operador as .


Creo que la mejor ''regla'' sería usar solo la palabra clave ''como'' cuando se espera que su sujeto no sea el objeto al que está enviando:

var x = GiveMeSomething(); var subject = x as String; if(subject != null) { // do what you want with a string } else { // do what you want with NOT a string }

Sin embargo, cuando tu tema DEBE ser del tipo al que estás recurriendo, usa un ''reparto clásico'', como lo llamas. Porque si no es del tipo que está esperando, obtendrá una excepción que se ajusta a la situación excepcional.


El operador as es útil en un par de circunstancias.

  1. Cuando solo necesita saber que un objeto es de un tipo específico, pero no es necesario que actúe específicamente sobre miembros de ese tipo
  2. Cuando desea evitar excepciones y, en cambio, tratar explícitamente con null
  3. Desea saber si hay una conversión de CLR entre los objetos y no solo una conversión definida por el usuario.

El tercer punto es sutil pero importante. No hay un mapeo 1-1 entre qué moldes tendrá éxito con el operador de fundición y los que tendrán éxito con el operador de. El operador as está estrictamente limitado a las conversiones de CLR y no tendrá en cuenta las conversiones definidas por el usuario (el operador de transmisión lo hará).

Específicamente, el operador as solo permite lo siguiente (de la sección 7.9.11 de la especificación Cng lang)

  • Una identidad (§6.1.1), referencia implícita (§6.1.6), boxeo (§6.1.7), referencia explícita (§6.2.4), o unboxing (§6.2.5) existe una conversión del tipo de E a T.
  • El tipo de E o T es un tipo abierto.
  • E es el literal nulo.

En algunos casos, es fácil tratar con un null que una excepción. En particular, el operador coalescente es útil:

SomeClass someObject = (obj as SomeClass) ?? new SomeClass();

También simplifica el código donde estás (sin usar polimorfismo, y) ramificación según el tipo de objeto:

ClassA a; ClassB b; if ((a = obj as ClassA) != null) { // use a } else if ((b = obj as ClassB) != null) { // use b }

Como se especifica en la página MSDN , el operador as es equivalente a:

expression is type ? (type)expression : (type)null

que evita la excepción completamente a favor de una prueba de tipo más rápida, pero también limita su uso a tipos que admiten null (tipos de referencia y Nullable<T> ).


La comparación nula es MUCHO más rápida que arrojar y atrapar excepciones. Las excepciones tienen una sobrecarga importante: el trazado de la pila debe ensamblarse, etc.

Las excepciones deben representar un estado inesperado, que a menudo no representa la situación (que es cuando funciona mejor).


La palabra clave as es útil cuando realmente no sabe de qué tipo puede ser la variable. Si tiene una sola función que seguirá diferentes rutas de código dependiendo del tipo real del parámetro, entonces tiene dos opciones:

Primero, usando un molde normal:

if(myObj is string) { string value = (string)myObj; ... do something } else if(myObj is MyClass) { MyClass = (MyClass)myObj; }

Esto requiere que compruebe el tipo de objeto que is usando para que no intente convertirlo en algo que fallará. Esto también es ligeramente redundante, ya que la comprobación de tipo is se realiza nuevamente en el molde (para que pueda lanzar la excepción si es necesario).

La alternativa es usar as .

string myString = myObj as string; MyClass myClass = myObj as MyClass; if(myString != null) { } else if(myClass != null) { }

Esto hace que el código sea algo más corto y también elimina la verificación de tipo redundante.


No hay nada profundo sucediendo aquí. Básicamente, es útil probar algo para ver si es de cierto tipo (es decir, usar ''como''). Debería verificar el resultado de la llamada ''como'' para ver si el resultado es nulo.

Cuando esperes que un elenco funcione y quieras que se emita la excepción, utiliza el método "clásico".


Supongo que es útil si el resultado del elenco se pasará a un método que usted sabe manejará las referencias nulas sin throwing y ArgumentNullException o similar.

Tiendo a encontrar muy poco uso para as , ya que:

obj as T

Es más lento que:

if (obj is T) ...(T)obj...

El uso de as es en gran as un escenario marginal para mí, así que no puedo pensar en ninguna regla general para cuando lo usaría más que para lanzar y manejar la excepción (más informativa) de lanzamiento más arriba en la pila.


Utiliza la instrucción "como" para evitar la posibilidad de una excepción, por ejemplo, puede manejar la falla de conversión elegantemente a través de la lógica. Solo use el yeso cuando esté seguro de que el objeto es del tipo deseado. Casi siempre uso el "como" y luego verifico nulo.


usando como se devolverá nulo si no es un lanzamiento válido que le permite hacer otras cosas además de envolver el elenco en un try / catch. Odio el elenco clásico. Siempre uso como yeso si no estoy seguro. Además, las excepciones son costosas. Los controles nulos no lo son.