Usando LINQ en colecciones, ¿cuál es la diferencia entre las siguientes líneas de código?
if(!coll.Any(i => i.Value))
y
if(!coll.Exists(i => i.Value))
Actualización 1
Cuando desarmo .Exists
parece que no hay código.
Actualización 2
Alguien sabe por qué no hay código para este?
c#
linq
collections
Anthony D
fuente
fuente
Respuestas:
Ver documentación
List.Exists (Método del objeto - MSDN)
Esto existe desde .NET 2.0, por lo tanto, antes de LINQ. Se debe utilizar con el delegado Predicate , pero las expresiones lambda son compatibles con versiones anteriores. Además, solo List tiene esto (ni siquiera IList)
IEnumerable.Any (Método de extensión - MSDN)
Esto es nuevo en .NET 3.5 y usa Func (TSource, bool) como argumento, por lo que estaba destinado a usarse con expresiones lambda y LINQ.
En comportamiento, estos son idénticos.
fuente
List<>
métodos de instancia de .NET 2 .La diferencia es que Any es un método de extensión para cualquier
IEnumerable<T>
definido en System.Linq.Enumerable. Se puede usar en cualquierIEnumerable<T>
instancia.Existe no parece ser un método de extensión. Supongo que coll es de tipo
List<T>
. Si es así, existe un método de instancia que funciona de manera muy similar a Any.En resumen , los métodos son esencialmente los mismos. Uno es más general que el otro.
fuente
TLDR; En cuanto al rendimiento,
Any
parece ser más lento (si configuré esto correctamente para evaluar ambos valores casi al mismo tiempo)generador de lista de prueba:
Con 10 millones de registros
Con 5 millones de registros
Con registros de 1M
Con 500k (también cambié el orden en el que se evalúan para ver si no hay ninguna operación adicional asociada con lo que se ejecute primero).
Con 100k registros
Parecería
Any
ser más lento por una magnitud de 2.Editar: para los registros de 5 y 10 millones, cambié la forma en que genera la lista y de
Exists
repente me volví más lento de loAny
que implica que hay algo mal en la forma en que estoy probando.Nuevo mecanismo de prueba:
Edit2: Ok, para eliminar cualquier influencia de la generación de datos de prueba, lo escribí todo en el archivo y ahora lo leí desde allí.
10 millones
5 millones
1M
500k
fuente
Como continuación de la respuesta de Matas sobre benchmarking.
TL / DR : Exists () y Any () son igualmente rápidos.
En primer lugar: la evaluación comparativa con el cronómetro no es precisa ( consulte la respuesta de series0ne sobre un tema diferente, pero similar ), pero es mucho más preciso que DateTime.
La forma de obtener lecturas realmente precisas es mediante el Perfil de rendimiento. Pero una forma de tener una idea de cómo se comparan el rendimiento de los dos métodos es ejecutando ambos métodos muchas veces y luego comparando el tiempo de ejecución más rápido de cada uno. De esa manera, realmente no importa que JITing y otros ruidos nos den malas lecturas (y lo hace ), porque ambas ejecuciones son " igualmente equivocadas " en cierto sentido.
Después de ejecutar el código anterior 4 veces (que a su vez tiene 1 000
Exists()
yAny()
en una lista con 1 000 000 elementos), no es difícil ver que los métodos son casi igual de rápidos.No es una ligera diferencia, pero es una diferencia demasiado pequeña como para no ser explicado por el ruido de fondo. Supongo que si uno hiciera 10 000 o 100 000
Exists()
yAny()
, en cambio, esa ligera diferencia desapareciera más o menos.fuente
Además, esto solo funcionará si Value es de tipo bool. Normalmente esto se usa con predicados. Cualquier predicado se usaría generalmente para determinar si hay algún elemento que satisfaga una condición dada. Aquí solo está haciendo un mapa desde su elemento i a una propiedad bool. Buscará una "i" cuya propiedad Value sea verdadera. Una vez hecho esto, el método devolverá verdadero.
fuente
Cuando corrija las mediciones, como se mencionó anteriormente: Cualquiera y existe, y agregando el promedio, obtendremos el siguiente resultado:
fuente