A menudo quiero verificar si un valor proporcionado coincide con uno en una lista (por ejemplo, al validar):
if (!acceptedValues.Any(v => v == someValue))
{
// exception logic
}
Recientemente, noté que ReSharper me pedía que simplificara estas consultas para:
if (acceptedValues.All(v => v != someValue))
{
// exception logic
}
Obviamente, esto es lógicamente idéntico, tal vez un poco más legible (si has hecho muchas matemáticas), mi pregunta es: ¿esto resulta en un impacto en el rendimiento?
Parece que debería (es decir, .Any()
suena como un cortocircuito, mientras que .All()
parece que no), pero no tengo nada que corrobore esto. ¿Alguien tiene un conocimiento más profundo sobre si las consultas resolverán lo mismo o si ReSharper me está desviando?
if (!sequence.Any(v => v == true))
. Si desea continuar sólo si todo lo que se ajusta a una cierta especificación:if (sequence.All(v => v < 10))
.Respuestas:
Implementación de
All
acuerdo con ILSpy (como en realidad fui y miré, en lugar del "bueno, ese método funciona un poco como ..." podría hacerlo si estuviéramos discutiendo la teoría en lugar del impacto).Implementación de
Any
acuerdo a ILSpy:Por supuesto, podría haber alguna diferencia sutil en la IL producida. Pero no, no, no lo hay. La IL es más o menos la misma, pero para la inversión obvia de devolver verdadero en la coincidencia de predicados versus devolver falso en la falta de coincidencia de predicados.
Esto es linq para objetos solo, por supuesto. Es posible que algún otro proveedor de linq trate a uno mucho mejor que el otro, pero si ese fuera el caso, es bastante aleatorio cuál obtuvo la implementación más óptima.
Parece que la regla se reduce únicamente a alguien que siente que
if(determineSomethingTrue)
es más simple y más legible queif(!determineSomethingFalse)
. Y para ser justos, creo que tienen un cierto punto en que a menudo me pareceif(!someTest)
confuso * cuando hay una prueba alternativa de igual verbosidad y complejidad que volvería a ser cierta para la condición sobre la que queremos actuar. Sin embargo, en realidad, personalmente no encuentro nada que favorezca una sobre la otra de las dos alternativas que ofrece, y tal vez me inclinaría ligeramente hacia la primera si el predicado fuera más complicado.* No es confuso ya que no entiendo, pero confuso como me preocupa que haya alguna razón sutil para la decisión que no entiendo, y se necesitan algunos saltos mentales para darse cuenta de que "no, simplemente decidieron hacerlo de esa manera, espera ¿para qué estaba mirando este bit de código otra vez? ... "
fuente
Any
volveráfalse
y, por!Any
lo tanto , volverátrue
, por lo que son idénticos.!test.Any(x => x.Key == 3 && x.Value == 1)
esos usosAll
estest.All(x => !(x.Key == 3 && x.Value == 1))
(que de hecho es equivalente atest.All(x => x.Key != 3 || x.Value != 1)
).Puede encontrar que estos métodos de extensión hacen que su código sea más legible:
Ahora en lugar de tu original
tu puedes decir
fuente
Ambos tendrían un rendimiento idéntico porque ambos detienen la enumeración después de que se puede determinar el resultado:
Any()
en el primer elemento, el predicado pasado se evalúatrue
yAll()
en el primer elemento al que se evalúa el predicadofalse
.fuente
All
cortocircuitos en el primer no partido, por lo que no es un problema.Un área de sutileza es que
Es verdad. Todos los elementos de la secuencia son pares.
Para más información sobre este método, consulte la documentación de Enumerable.All .
fuente
bool allEven = !Enumerable.Empty<int>().Any(i => i % 2 != 0)
es cierto.All()
determina si todos los elementos de una secuencia satisfacen una condición.Any()
determina si algún elemento de una secuencia cumple la condición.fuente
De acuerdo a este enlace
fuente
Como otras respuestas han cubierto bien: no se trata de rendimiento, se trata de claridad.
Hay un amplio soporte para sus dos opciones:
Pero creo que esto podría lograr un apoyo más amplio :
Simplemente calcular el booleano (y nombrarlo) antes de negar cualquier cosa me aclara mucho esto.
fuente
Si echas un vistazo a la fuente Enumerable , verás que la implementación de
Any
yAll
está bastante cerca:No hay forma de que un método sea significativamente más rápido que el otro, ya que la única diferencia radica en una negación booleana, por lo que prefiere la legibilidad sobre la ganancia de rendimiento falso.
fuente