no System.Linq
espaço para nome, agora podemos estender nossos IEnumerable para ter os métodos de extensão Any () e Count () .
Foi-me dito recentemente que, se eu quiser verificar se uma coleção contém 1 ou mais itens, devo usar o .Any()
método de extensão em vez do método de .Count() > 0
extensão, porque o .Count()
método de extensão precisa percorrer todos os itens.
Em segundo lugar, algumas coleções têm uma propriedade (não um método de extensão) que é Count
ou Length
. Seria melhor usá-los, em vez de .Any()
ou .Count()
?
sim / não?
.net
linq
performance
.net-3.5
extension-methods
Pure.Krome
fonte
fonte
Respostas:
Se você está começando com algo que tem um
.Length
ou.Count
(comoICollection<T>
,IList<T>
,List<T>
, etc.) - então esta será a opção mais rápida, uma vez que não precisa passar peloGetEnumerator()
/MoveNext()
/Dispose()
seqüência necessária porAny()
para verificar se há um não-vaziaIEnumerable<T>
seqüência .Por apenas
IEnumerable<T>
, em seguida,Any()
irá geralmente ser mais rápido, uma vez que só tem de olhar para uma iteração. No entanto, observe que a implementação do LINQ-to-ObjectsCount()
verificaICollection<T>
(usando.Count
como uma otimização) - portanto, se a fonte de dados subjacente for diretamente uma lista / coleção, não haverá uma grande diferença. Não me pergunte por que não usa o não genéricoICollection
...Obviamente, se você usou o LINQ para filtrá-lo, etc (
Where
etc), terá uma sequência baseada em bloco iterador e, portanto, essaICollection<T>
otimização é inútil.Em geral com
IEnumerable<T>
: fique comAny()
;-pfonte
(somecollection.Count > 0)
? Todo o nosso código antes da introdução do método .Any () do LINQ era difícil de entender?someCollection.Count > 0
é tão claro quantosomeCollection.Any()
e tem o benefício adicional de maior desempenho e de não exigir o LINQ. Concedido, este é um caso muito simples e outras construções que usam operadores LINQ transmitirão a intenção dos desenvolvedores muito mais clara que a opção equivalente não-LINQ.Nota: Eu escrevi esta resposta quando o Entity Framework 4 era real. O objetivo desta resposta não era entrar em testes triviais
.Any()
versus.Count()
testes de desempenho. O objetivo era sinalizar que a EF está longe de ser perfeita. Versões mais recentes são melhores ... mas se você tiver parte do código que é lenta e usa EF, teste com TSQL direto e compare o desempenho em vez de confiar em suposições (que.Any()
é SEMPRE mais rápida que.Count() > 0
).Embora eu concorde com a maioria das respostas e comentários votados - especialmente sobre a intenção dos desenvolvedores de
Any
sinais pontuais melhor do que -, tive uma situação em que Count é mais rápido por ordem de grandeza no SQL Server (EntityFramework 4).Count() > 0
Aqui está a consulta com
Any
essa exceção de tempo limite (em ~ 200.000 registros):Count
versão executada em questão de milissegundos:Preciso encontrar uma maneira de ver o SQL exato que ambos os LINQs produzem - mas é óbvio que há uma enorme diferença de desempenho entre
Count
e,Any
em alguns casos, e, infelizmente, parece que você não pode ficarAny
em todos os casos.Edição: Aqui são gerados SQLs. Belezas como você pode ver;)
ANY
:COUNT
:Parece que puro Where with EXISTS funciona muito pior do que calcular Count e depois fazer Where with Count == 0.
Deixe-me saber se vocês vêem algum erro nas minhas descobertas. O que se pode tirar disso tudo, independentemente da discussão Any vs Count, é que qualquer LINQ mais complexo fica muito melhor quando reescrito como Procedimento Armazenado;).
fonte
Como esse é um tópico bastante popular e as respostas diferem, tive que dar uma nova olhada no problema.
Ambiente de teste: EF 6.1.3, SQL Server, 300k registros
Modelo de tabela :
Código do teste:
Resultados:
Qualquer () ~ 3ms
Count () ~ 230ms para a primeira consulta, ~ 400ms para a segunda
Observações:
Para o meu caso, a EF não gerou SQL como o @Ben mencionado em seu post.
fonte
Count() > 0
. : DEDIT: foi corrigido na versão EF 6.1.1. e essa resposta não é mais real
Para SQL Server e EF4-6, Count () executa cerca de duas vezes mais rápido que Any ().
Quando você executa o Table.Any (), ele gera algo como ( alerta: não machuque o cérebro tentando entendê-lo )
isso requer 2 varreduras de linhas com sua condição.
Não gosto de escrever
Count() > 0
porque esconde minha intenção. Eu prefiro usar predicado personalizado para isso:fonte
Depende, qual o tamanho do conjunto de dados e quais são seus requisitos de desempenho?
Se não é nada gigantesco, use a forma mais legível, o que para mim é alguma, porque é mais curta e legível do que uma equação.
fonte
Sobre o método Count () , se o IEnumarable é um ICollection , não podemos iterar em todos os itens, pois podemos recuperar o campo Count de ICollection , se o IEnumerable não for um ICollection , devemos iterar todos os itens usando um tempo com um MoveNext , dê uma olhada no Código do .NET Framework:
Referência: Origem de Referência Enumerável
fonte
Você pode fazer um teste simples para descobrir isso:
Verifique os valores de testCount e testAny.
fonte
Count
substituído pelo método Count () vs .Any () não uma propriedade. Você precisa de tempo de iterações.Se você estiver usando o Entity Framework e tiver uma tabela enorme com muitos registros, Any () será muito mais rápido. Lembro-me de uma vez que queria verificar se uma tabela estava vazia e tinha milhões de linhas. Foram necessários 20 a 30 segundos para que Count ()> 0 fosse concluído. Foi instantâneo com Any () .
Qualquer () pode ser um aprimoramento de desempenho, pois talvez não seja necessário iterar a coleção para obter o número de coisas. Só tem que acertar um deles. Ou, por exemplo, LINQ para entidades, o SQL gerado será SE EXISTE (...) em vez de SELECIONAR CONTAGEM ... ou até SELECIONAR * ....
fonte