type safe operator convert conversion cast another c# casting type-conversion

safe - cast<> c#



¿Tiene sentido utilizar "como" en lugar de una conversión incluso si no hay una comprobación nula? (13)

A la gente le gusta tanto porque les hace sentirse a salvo de las excepciones ... Como garantía en una caja. Un chico pone una garantía elegante en la caja porque quiere que te sientas cálido y cálido por dentro. Crees que pusiste esa cajita debajo de tu almohada por la noche, el Fairy de Garantía podría bajar y dejar un cuarto, ¿verdad, Ted?

De vuelta en el tema ... cuando se usa una conversión directa, existe la posibilidad de una excepción de conversión no válida. Por lo tanto, las personas aplican as una solución general a todas sus necesidades de lanzamiento porque as (por sí misma) nunca lanzará una excepción. Pero lo gracioso de eso es el ejemplo que dio (x as T).SomeMethod(); está intercambiando una excepción de conversión no válida por una excepción de referencia nula. Lo que confunde el problema real cuando ves la excepción.

Generalmente no uso mucho. Prefiero la prueba is porque para mí, parece más legible y tiene más sentido que intentar un lanzamiento y comprobar si está nulo.

En los blogs de desarrollo, ejemplos de códigos en línea y (recientemente) incluso un libro, sigo tropezando con códigos como este:

var y = x as T; y.SomeMethod();

o, peor aún:

(x as T).SomeMethod();

Eso no tiene sentido para mí. Si está seguro de que x es del tipo T , debe usar un lanzamiento directo: (T)x . Si no está seguro, puede usar as pero necesita verificar si está null antes de realizar alguna operación. Todo lo que hace el código anterior es convertir una ( InvalidCastException (útil) en una ( NullReferenceException (inútil)).

¿Soy el único que piensa que esto es un abuso flagrante de la palabra clave? ¿O me perdí algo obvio y el patrón anterior realmente tiene sentido?


A menudo he visto referencias a este artículo engañoso como evidencia de que "como" es más rápido que el casting.

Uno de los aspectos engañosos más obvios de este artículo es el gráfico, que no indica lo que se está midiendo: sospecho que está midiendo moldes fallidos (donde "como" es obviamente mucho más rápido ya que no se lanza ninguna excepción).

Si se toma el tiempo para realizar las mediciones, verá que el lanzamiento es, como es de esperar, más rápido que "como" cuando el lanzamiento tiene éxito.

Sospecho que esto puede ser una razón para el uso de la palabra clave "culto de carga" en lugar de un reparto.


Creo que la palabra clave as podría considerarse como una versión más elegante del dynamic_cast de C ++.


El 99% del tiempo cuando uso "como" es cuando no estoy seguro de cuál es el tipo de objeto real

var x = obj as T; if(x != null){ //x was type T! }

y no quiero capturar excepciones de reparto explícitas ni hacer el lanzamiento dos veces, usando "es":

//I don''t like this if(obj is T){ var x = (T)obj; }


El lanzamiento directo necesita un par de paréntesis más que la palabra clave as . Así que incluso en el caso de que esté 100% seguro de cuál es el tipo, reduce el desorden visual.

De acuerdo con la excepción, sin embargo. Pero al menos para mí, la mayoría de los usos se reducen para comprobar si hay un null después, lo que me parece más agradable que detectar una excepción.


El uso de ''como'' no aplica las conversiones definidas por el usuario, mientras que el reparto los usará cuando sea apropiado. Eso puede ser una diferencia importante en algunos casos.


En mi humilde opinión, tiene sentido cuando se combina con un cheque null :

var y = x as T; if (y != null) y.SomeMethod();


Es solo porque a la gente le gusta su apariencia, es muy legible.

Enfrentémoslo: el operador de conversión / conversión en lenguajes tipo C es bastante terrible, en términos de legibilidad. Me gustaría más si C # adoptara la sintaxis de Javascript de:

object o = 1; int i = int(o);

O defina un operador a, el equivalente de casting de as :

object o = 1; int i = o to int;


Escribí un poco sobre esto aquí:

blogs.msdn.com/ericlippert/archive/2009/10/08/…

Entiendo tu punto. Y estoy de acuerdo con la idea: que un operador de conversión comunica "Estoy seguro de que este objeto se puede convertir a ese tipo, y estoy dispuesto a arriesgarme a una excepción si me equivoco", mientras que un operador "como" se comunica "No estoy seguro de que este objeto se pueda convertir a ese tipo; dame un nulo si me equivoco".

Sin embargo, hay una diferencia sutil. (x como T). Lo que () comunica "Sé que no solo se puede convertir x a T, sino que además implica que solo se realizan conversiones de referencia o de desempaquetado y, además, que x no es nulo". Eso comunica información diferente a ((T) x). Lo que sea (), y tal vez eso es lo que pretende el autor del código.


Esta tiene que ser una de mis mejores mangas .

El D&E de Stroustrup y / o alguna publicación de blog que no puedo encontrar en este momento analiza la noción de un operador to que abordaría el punto señalado por https://.com/users/73070/johannes-rossel (es decir, la misma sintaxis as pero con semántica DirectCast ).

La razón por la que esto no se implementó es porque un yeso debe causar dolor y ser feo, por lo que se lo aleja del uso.

Lástima que los programadores "inteligentes" (a menudo autores de libros (Juval Lowy IIRC)) eviten esto abusando de esta manera (C ++ no ofrece un as , probablemente por esta razón).

¡Incluso VB tiene más consistencia en tener una sintaxis uniforme que te obliga a elegir un TryCast o DirectCast y DirectCast !


Probablemente sea más popular sin ninguna razón técnica, pero solo porque es más fácil de leer y más intuitivo. (No decir que lo hace mejor tratando de responder la pregunta)


Tu entendimiento es verdadero. Eso suena como intentar micro-optimizar para mí. Debes usar un modelo normal cuando estés seguro del tipo. Además de generar una excepción más sensible, también falla rápidamente. Si está equivocado acerca de su suposición sobre el tipo, su programa fallará de inmediato y podrá ver la causa de la falla inmediatamente en lugar de esperar una excepción NullReferenceException o ArgumentNullException o incluso un error lógico en el futuro. En general, una expresión as que no está seguida por una comprobación null algún lugar es un olor de código.

Por otro lado, si no está seguro acerca del lanzamiento y espera que falle, debe usarlo as lugar de un lanzamiento normal envuelto con un bloque try-catch . Por otra parte, el uso de as se recomienda sobre una verificación de tipo seguida por un modelo. En lugar de:

if (x is SomeType) ((SomeType)x).SomeMethod();

que genera una instrucción isinst para la palabra clave is y una instrucción castclass para la castclass (que se realiza efectivamente la castclass dos veces), debe usar:

var v = x as SomeType; if (v != null) v.SomeMethod();

Esto solo genera una instrucción isinst . El método anterior tiene una falla potencial en aplicaciones de multiproceso, ya que una condición de carrera podría hacer que la variable cambie su tipo después de que la verificación sea exitosa y falle en la línea de lanzamiento. El último método no es propenso a este error.

La siguiente solución no se recomienda para uso en el código de producción. Si realmente odias una construcción tan fundamental en C #, puedes considerar cambiar a VB o algún otro idioma.

En caso de que uno odie desesperadamente la sintaxis del reparto, puede escribir un método de extensión para imitar el reparto:

public static T To<T>(this object o) { // Name it as you like: As, Cast, To, ... return (T)o; }

y usa una sintaxis limpia [?]:

obj.To<SomeType>().SomeMethod()


Una razón para usar "como":

T t = obj as T; //some other thread changes obj to another type... if (t != null) action(t); //still works

En lugar de (código erróneo):

if (obj is T) { //bang, some other thread changes obj to another type... action((T)obj); //InvalidCastException }