Noté que Resharper sugiere que cambie esto:
if (myObj.myProp is MyType)
{
...
}
dentro de esto:
var myObjRef = myObj.myProp as MyType;
if (myObjRef != null)
{
...
}
¿Por qué sugeriría este cambio? Estoy acostumbrado a que Resharper sugiera cambios de optimización y cambios de reducción de código, pero parece que quiere tomar mi declaración única y convertirla en dos líneas.
Según MSDN :
Una expresión is se evalúa como verdadera si se cumplen las dos condiciones siguientes:
la expresión no es nula. la expresión se puede convertir al tipo . Es decir, una expresión de conversión del formulario
(type)(expression)
se completará sin generar una excepción.
¿Estoy malinterpretando eso, o no is
hago exactamente las mismas verificaciones, solo en una sola línea sin la necesidad de crear explícitamente otra variable local para la verificación nula?
MyProp
getter después de este cambio.Respuestas:
Porque solo hay un elenco. Compare esto:
a esto:
C # 7.0 admite una sintaxis más compacta mediante la coincidencia de patrones :
fuente
as
puede ser un par de nanosegundos más rápido, pero considero que esto es una microoptimización prematura.myObj
omyProp
podría cambiar (por otro hilo) entre elis
y el elenco, provocando un comportamiento no deseado.as
+!= null
también ejecutará el!=
operador anulado deMyType
si está definido (incluso simyObjRef
es nulo). Si bien en la mayoría de los casos esto no es un problema (especialmente si lo implementa correctamente), en algunos casos extremos (código incorrecto, rendimiento) puede que no sea deseado. (Sin embargo, tendría que ser bastante extremo )object.ReferenceEquals(null, myObjRef)
.La mejor opción es usar la coincidencia de patrones como esa:
fuente
Todavía no hay información sobre lo que realmente sucede debajo del cinturón. Echale un vistazo a éste ejemplo:
Esto se traduce en la siguiente IL:
Lo que importa aquí son las llamadas
isinst
ycastclass
, ambas relativamente caras. Si compara eso con la alternativa, puede ver que solo hace unaisinst
verificación:También vale la pena mencionar que un tipo de valor usará en
unbox.any
lugar decastclass
:Sin embargo, tenga en cuenta que esto no se traduce necesariamente en un resultado más rápido, como podemos ver aquí . No parece haber habido mejoras desde que se hizo esa pregunta sin embargo: moldes parecen ser realizada tan rápido como lo que solía ser, pero
as
ylinq
ahora son aproximadamente 3 veces más rápido.fuente
Advertencia de reafilado:
"Type check and direct cast can be replaced with try cast and check for null"
Ambos funcionarán, depende de cómo le convenga más su código. En mi caso, simplemente ignoro esa advertencia:
En mi código, la segunda forma es un rendimiento más largo y peor.
fuente
IRunable
. Si no tienes el control, ¿quizás podrías usarlodynamic
?Para mí, esto parece depender de las probabilidades de que sea de ese tipo o no. Ciertamente, sería más eficiente hacer el yeso por adelantado si el objeto es de ese tipo la mayor parte del tiempo. Si solo es ocasionalmente de ese tipo, entonces puede ser más óptimo verificar primero con is.
El costo de crear una variable local es muy insignificante en comparación con el costo de la verificación de tipo.
La legibilidad y el alcance son los factores más importantes para mí normalmente. No estaría de acuerdo con ReSharper y usaría el operador "es" solo por esa razón; optimizar más tarde si se trata de un verdadero cuello de botella.
(Supongo que solo está usando
myObj.myProp is MyType
una vez en esta función)fuente
También debería sugerir un segundo cambio:
dentro
Esto ahorra un acceso a la propiedad y un elenco, en comparación con el código original. Pero solo es posible después de cambiar
is
aas
.fuente
(MyType)
arrojará una excepción si el lanzamiento falla.as
solo devolucionesnull
.is
(ese código está en la pregunta).Yo diría que esto es para hacer una versión fuertemente tipada de myObj.myProp, que es myObjRef. Esto debe usarse cuando haga referencia a este valor en el bloque, en lugar de tener que hacer un lanzamiento.
Por ejemplo, esto:
es mejor que esto:
fuente