319 votos

¿Tiene sentido utilizar "como" en lugar de un yeso, incluso si no hay un control nulo?

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

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

o, aún peor:

(x as T).SomeMethod();

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

Soy yo el único que piensa que este es un flagrante abuso de la as de palabras clave? O ¿se me olvida algo que es obvio y el modelo anterior tiene sentido en realidad?

230voto

Mehrdad Afshari Puntos 204872

Su comprensión es verdadera. Eso suena como tratando de micro-optimizar para mí. Usted debe utilizar un normal fundido cuando se está seguro del tipo. Además de generar más sensible excepción, también falla rápido. Si usted está equivocado acerca de su hipótesis sobre el tipo, el programa fallará inmediatamente y usted será capaz de ver la causa de la falla de inmediato en lugar de esperar que un NullReferenceException o ArgumentNullException o incluso un error lógico en algún momento en el futuro. En general, un as expresión que no es seguido por un null compruebe en algún lugar es un código de olor.

Por otro lado, si usted no está seguro sobre el molde y esperar a fallar, debe utilizar as en lugar de una normal yeso envuelto con un try-catch bloque. Por otra parte, el uso de as se recomienda más de un tipo de verificación seguido por un lanzamiento. En lugar de:

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

que genera un isinst instrucción para la is de palabras clave, y un castclass instrucción para el yeso (de hecho la realización de la fundición de dos veces), se debe usar:

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

Esto sólo genera un isinst instrucción. El primer método tiene un potencial defecto en aplicaciones multiproceso como una condición de anticipación podría causar que la variable para cambiar su tipo después de la is de verificación éxito y fracasar en el elenco de la línea. El último método no es propenso a este error.


La siguiente solución es no se recomienda para su uso en el código de producción. Si realmente odio como un elemento esencial de la construcción en C#, usted podría considerar la posibilidad de cambiar a VB o algún otro idioma.

En caso de que uno desesperadamente odia el elenco de la sintaxis, él/ella puede escribir un método de extensión para imitar el elenco:

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

y el uso de una cuidada[?] sintaxis:

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

39voto

Rubens Farias Puntos 33357

En mi humilde opinión, as sólo tiene sentido cuando se combina con un null de verificación:

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

34voto

Larry Fix Puntos 443

El uso de 'como' no se aplica conversiones definidas por el usuario, mientras que el elenco los utilizará en su caso. Eso puede ser una diferencia importante en algunos casos.

33voto

Eric Lippert Puntos 300275

Escribí un poco acerca de esto aquí:

http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx

Entiendo tu punto. Y estoy de acuerdo con la idea central: que un operador de conversión se comunica "estoy seguro de que este objeto se puede convertir a ese tipo, y estoy dispuesto a arriesgar una excepción si estoy equivocado", mientras que el "como" operador se comunica "no estoy seguro de que este objeto se puede convertir a ese tipo; me dan un valor null si estoy equivocado".

Sin embargo, hay una sutil diferencia. (x T).Whatever() se comunica "sé que no es justo que x puede ser convertido a una T, pero por otra parte, que ello implica sólo de referencia o unboxing de conversiones, y además, que x no es nulo". Que hace comunicar información diferente (a(T)x).Whatever(), y tal vez eso es lo que el autor de el código pretende.

15voto

Joe Puntos 60749

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

Uno de los más obvios engañosa los aspectos de este artículo es el gráfico, que no indica lo que se está midiendo: tengo la sospecha de medición de error de yesos (donde el "como" es, obviamente, mucho más rápido ya que no se emite ninguna excepción).

Si usted toma el tiempo para hacer las mediciones, luego verás que la conversión es, como era de esperar, más rápido que el de "como" cuando el reparto se realiza correctamente.

Sospecho que esto puede ser una razón para el "cargo cult" el uso de la palabra clave en lugar de un yeso.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X