Dada una gran colección de objetos, ¿hay alguna diferencia de rendimiento entre los siguientes?
myCollection.Contains(myElement)
myCollection.Any(currentElement => currentElement == myElement)
Dada una gran colección de objetos, ¿hay alguna diferencia de rendimiento entre los siguientes?
myCollection.Contains(myElement)
myCollection.Any(currentElement => currentElement == myElement)
Respuestas:
Contains()es un método de instancia y su rendimiento depende en gran medida de la colección en sí. Por ejemplo, Contains()en a Listes O (n), mientras que Contains()en a HashSetes O (1).
Any()es un método de extensión, y simplemente recorrerá la colección, aplicando el delegado en cada objeto. Por tanto, tiene una complejidad de O (n).
Any()sin embargo, es más flexible ya que puede pasar un delegado. Contains()solo puede aceptar un objeto.
Containstambién es un método de extensión contra IEnumerable<T>(aunque algunas colecciones también tienen su propio Containsmétodo de instancia). Como dice, Anyes más flexible que Containsporque puede pasarle un predicado personalizado, pero Contains podría ser un poco más rápido porque no necesita realizar una invocación delegada para cada elemento.
All()opera de manera similar.
Depende de la colección. Si tiene una colección ordenada, entonces Containspodría hacer una búsqueda inteligente (binaria, hash, árbol b, etc.), mientras que con `Any () básicamente está atascado con la enumeración hasta que la encuentre (asumiendo LINQ-to-Objects) .
También tenga en cuenta que en su ejemplo, Any()está usando el ==operador que verificará la igualdad de referencia, mientras Containsque usará IEquatable<T>o el Equals()método, que podría ser anulado.
Supongo que dependerá del tipo de myCollectiones el que dicta cómo Contains()se implementa. Si, por ejemplo, un árbol binario ordenado, podría buscar de forma más inteligente. También puede tener en cuenta el hash del elemento. Any()por otro lado se enumerará a través de la colección hasta que se encuentre el primer elemento que satisfaga la condición. No hay optimizaciones para si el objeto tenía un método de búsqueda más inteligente.
Contains () también es un método de extensión que puede funcionar rápidamente si lo usa de la manera correcta. Por ejemplo:
var result = context.Projects.Where(x => lstBizIds.Contains(x.businessId)).Select(x => x.projectId).ToList();
Esto le dará a la consulta
SELECT Id
FROM Projects
INNER JOIN (VALUES (1), (2), (3), (4), (5)) AS Data(Item) ON Projects.UserId = Data.Item
mientras que Any () por otro lado siempre itera a través de O (n).
Espero que esto funcione ...