Usando o LINQ em coleções, qual é a diferença entre as seguintes linhas de código?
if(!coll.Any(i => i.Value))
e
if(!coll.Exists(i => i.Value))
Atualização 1
Quando desmonte .Exists
, parece que não há código.
Atualização 2
Alguém sabe por que não existe um código para este?
c#
linq
collections
Anthony D
fonte
fonte
Respostas:
Ver documentação
List.Exists (método de objeto - MSDN)
Isso existe desde o .NET 2.0, portanto, antes do LINQ. Era para ser usado com o delegado do Predicado , mas as expressões lambda são compatíveis com versões anteriores. Além disso, apenas a List possui isso (nem mesmo o IList)
IEnumerable.Any (método de extensão - MSDN)
Isso é novo no .NET 3.5 e usa Func (TSource, bool) como argumento; portanto, ele deveria ser usado com expressões lambda e LINQ.
No comportamento, estes são idênticos.
fonte
List<>
métodos de instância do .NET 2 .A diferença é que Any é um método de extensão para qualquer
IEnumerable<T>
definido em System.Linq.Enumerable. Pode ser usado em qualquerIEnumerable<T>
instância.Existe não parece ser um método de extensão. Meu palpite é que coll é do tipo
List<T>
. Se houver, existe um método de instância que funciona muito semelhante a Qualquer.Em suma , os métodos são essencialmente os mesmos. Um é mais geral que o outro.
fonte
TLDR; O desempenho
Any
parece mais lento (se eu tiver configurado isso corretamente para avaliar os dois valores quase ao mesmo tempo)gerador de lista de testes:
Com 10 milhões de registros
Com registros de 5 milhões
Com 1 milhão de registros
Com 500k, (também inverti a ordem na qual eles são avaliados para ver se não há nenhuma operação adicional associada ao que ocorrer primeiro).
Com 100 mil registros
Parece
Any
ser mais lento pela magnitude de 2.Edit: Para registros de 5 e 10 milhões, mudei a maneira como gera a lista e, de
Exists
repente, fiquei mais lento do que oAny
que implica que há algo errado na maneira como estou testando.Novo mecanismo de teste:
Edit2: Ok, para eliminar qualquer influência da geração de dados de teste, escrevi tudo para arquivar e agora li a partir daí.
10 milhões
5M
1 milhão
500k
fonte
Como continuação da resposta de Matas sobre benchmarking.
TL / DR : existe () e Qualquer () são igualmente rápidos.
Primeiro: o benchmarking usando o cronômetro não é preciso ( consulte a resposta da série0ne sobre um tópico diferente, mas semelhante ), mas é muito mais preciso que o DateTime.
A maneira de obter leituras realmente precisas é usando o Performance Profiling. Mas uma maneira de ter uma noção de como medir o desempenho dos dois métodos-se uns aos outros é através da execução de ambos os métodos cargas de vezes e, em seguida, comparando o tempo de execução mais rápida de cada um. Dessa forma, realmente não importa que o JIT e outros ruídos nos proporcionem leituras ruins (e o fazem ), porque ambas as execuções são " igualmente equivocadas " em certo sentido.
Depois de executar o código acima 4 vezes (que por sua vez faz 1 000
Exists()
eAny()
em uma lista com 1 000 000 elementos), não é difícil ver que os métodos são praticamente igualmente rápidos.Não é uma pequena diferença, mas é diferença que um pequeno demais para não ser explicado pelo ruído de fundo. Meu palpite seria que, se um faria 10 000 ou 100 000
Exists()
eAny()
em vez disso, que leve diferença desapareceria mais ou menos.fonte
Além disso, isso só funcionará se Valor for do tipo bool. Normalmente, isso é usado com predicados. Qualquer predicado geralmente seria usado para descobrir se existe algum elemento que satisfaça uma determinada condição. Aqui você está apenas fazendo um mapa do seu elemento i para uma propriedade bool. Ele procurará um "i" cuja propriedade Value seja verdadeira. Uma vez feito, o método retornará verdadeiro.
fonte
Quando você corrige as medidas - como mencionado acima: Qualquer e Existe, e adicionando média -, obteremos a seguinte saída:
fonte