Qual é o uso de .Any () em uma lista de C # <>?


40

Eu estive discutindo isso com os colegas, e nós não poderíamos descobrir o que o uso é de .Anypara qualquer dado List<>, em C #.

Você pode verificar a validade de um elemento na matriz como a seguinte declaração:

if (MyList.Any()){ ...}  //Returns true or false

Qual é exatamente o mesmo que

if (MyList.Count() != 0) { ... }

e é muito mais comum, legível e claro sobre a intenção da ifdeclaração.

No final, ficamos presos a esse pensamento:

.Any() pode ser usado, funcionará da mesma forma, mas é menos claro sobre a intenção do programador e, nesse caso, não deve ser usado.

Mas sentimos que isso não pode estar certo; devemos estar faltando alguma coisa.

Nós somos?


40
de que maneira é menos clara a intenção?
jk.

35
Eu desafio sua afirmação que Any()é menos clara: Any()parece mais clara para mim, especialmente com uma condição lambda. A tradução do código para o inglês na minha cabeça if(MyList.Count(o => o > 10) > 0)se torna "O número de itens é maior que 10 e mais que 0?" enquanto if(MyList.Any(o => o > 10))torna-se "Existem itens maiores que 10?"
BlueRaja - Danny Pflughoeft 4/15

3
@SargeBorsch - somente se você preferir nomes de Heskel / funcional, o que a maioria das pessoas não.
Davor Ždralo 5/09/2015

4
@ BlueRaja-DannyPflughoeft eu concordo. Eu acho que qualquer um é mais claro, pois elimina um que poderia ser considerado um número mágico.
Andy Andy

2
@SargeBorsch: O SQL paralela à Anyseja Exists. O nome Linq provavelmente é mais inspirado em Haskell e Python, que também possuem todas / todas as funções.
JacquesB

Respostas:


95

Lembre-se de que Anynão opera em um List; opera em um IEnumerable, que representa um tipo concreto que pode ou não ter uma Countpropriedade. É verdade que não é necessariamente a melhor coisa a ser usada em um List, mas definitivamente é útil no final de uma consulta LINQ. E ainda mais útil que a versão autônoma é a substituição que requer um predicado da mesma forma Where. Não há nada embutido Listque seja tão conveniente ou expressivo quanto o Anymétodo de extensão de predicado .

Além disso, se você estiver usando Count()(o método de extensão LINQ para IEnumerable), em vez de Count(a propriedade ativada List), pode ser necessário enumerar a sequência inteira se não puder otimizar isso, detectando que o tipo de dados subjacente possui uma Countpropriedade . Se você tiver uma sequência longa, isso pode ser um impacto perceptível no desempenho quando você realmente não se importa com o que é a contagem e só quer saber se há algum item na coleção.


19
Este. Desempenho de lado, Any()com um predicado é mais expressivo do que comparando a substituição da Enumerable.Count()que leva um predicado com 0. :)
Dan J

1
Eu acho que isso explica os fundamentos tão claramente que explica a melhor resposta.
Tarik

2
IMHO, Existsé tão conveniente e expressivo quanto Any, com um predicado. Usar a Count != 0propriedade a Listé mais normal do que usar Any(). É apenas preferência pessoal. Também passei pelo esforço de mudar _list_.Count()para _list_.Counto código do meu grupo. Isso fez uma diferença notável para mim.
Suncat2000

55

Há uma diferença no tempo de execução que Count()pode ser O (n) onde Any()é O (1).


15
Count()também não será interrompido por iteradores infinitos, enquanto Any()será, pois ele precisará chamar apenas MoveNext()uma vez.
21416 Jon Purdy

3
Sucinto e preciso, mas isso parece mais um comentário do que uma resposta. Os programadores preferem respostas que se aprofundam no porquê e fornecem uma medida de explicação. Considere editar sua resposta e expandir por que O (1) pode ser (é) importante.

resposta muito boa só soube que eu deveria usar qualquer em vez de contagem == 0: d
MonsterMMORPG

4
Any(Func<T>)é O (n)
BlueRaja - Danny Pflughoeft 4/15

1
No caso específico de List, o desempenho é o mesmo porque a extensão usa a propriedade Verdadeiro para todas as coleções que implementam a ICollectioninterface.
Thorkil Holm-Jacobsen

9

Na verdade, lembre-se de que existe a propriedade List.Count e, em seguida, o método Enumerable.Count .

No seu exemplo, você está usando o Enumerable.Count()método, que precisa percorrer todos os itens da enumeração para retornar um resultado. Isso é claramente mais lento que a chamada, Any()que só precisa iterar sobre o primeiro item, se existir.

EDITAR:

Nos comentários, foi indicado, com razão, que o Enumerable.Count()método de extensão não precisa percorrer todos os itens se detectar que o enumerável também é um ICollection<T>. Portanto, no caso de a List<T>, usar a Countpropriedade ou o método não faz diferença.

Fonte IEnumerable.Count :

public static int Count<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    ICollection<TSource> collectionoft = source as ICollection<TSource>;
    if (collectionoft != null) return collectionoft.Count;
    ICollection collection = source as ICollection;
    if (collection != null) return collection.Count;
    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator()) {
        checked {
            while (e.MoveNext()) count++;
        }
    }
    return count;
}

Justo. E o uso da propriedade .Count então? isso não tornaria a leitura significativamente mais rápida, talvez tão rápida ou até mais rápida do que chamar .Any ()?
Gil Sand

4
Com uma List<T>diferença de desempenho será insignificante. Então, basta usar o que você preferir. Mas para outros tipos de IEnumerables, você só escolhe entre Count()(o método) e Any(), nesse caso, Any()sempre será o vencedor claro do seu caso de uso e deve ser o preferido. Pelo que vale, acho que Any()é bastante legível e claro.
sstan 04/09/2015

@sstan sim, a menos que, se o ienumerable puder ser convertido em uma colisão, ele possa ser otimizado e não importará.
Esben Skov Pedersen

2
Count()tem a mesma complexidade que Countpara ICollections, pois o método de extensão usa a propriedade em vez de iterar.
Thorkil Holm-Jacobsen

As extensões Linq são otimizadas para interfaces conhecidas - IList, ICollection. Discussão desempenho aqui é totalmente redundante, mesmo se esse é um detalhe de implementação
Gusdor

6

Uma pergunta surpreendente - acho que a intenção de list.Any()ser muito mais clara do que a intenção de list.Count()!=0.

Intenção significa: Se você leu o código de alguém (e não o escreveu), é completamente óbvio o que o programador deseja alcançar e por que ele foi escrito como está? Se um problema comum for resolvido de uma maneira desnecessariamente complexa, você imediatamente suspeita e se pergunta por que o desenvolvedor não usou a maneira simples. Você examina o código e tenta ver se perdeu alguma coisa. Você tem medo de alterar o código porque se preocupa com a falta de algum efeito colateral, e sua alteração pode causar problemas inesperados.

A intenção de usar o Any()método é completamente clara - você deseja saber se há algum elemento na lista ou não.

A intenção da expressão, Count()!=0por outro lado, não é óbvia para o leitor. Obviamente, não é difícil ver que a expressão diz se a lista está vazia ou não. As perguntas surgem porque você a escreve dessa maneira específica, em vez de usar o método padrão. Por que você usa Count()explicitamente? Se você realmente precisa apenas saber se há algum elemento em uma lista, por que deseja contar a lista inteira primeiro? Assim que você chegar a 1, você já tem sua resposta. Se a fonte fosse um iterador em uma coleção grande (talvez infinita) ou fosse traduzida para sql, isso poderia fazer uma grande diferença no desempenho. Então, talvez o uso explícito de Count () seja forçar uma consulta adiada para executar ou percorrer um iterador?

Mas a fonte é realmente um List<T>onde Count()é O (1) e não tem efeitos colaterais. Mas se o código se baseia nessa propriedade de List<T>, por que não usar a Countpropriedade-que indica mais claramente que você espera uma operação O (1) sem efeitos colaterais?

Como está escrito, list.Count()!=0faz exatamente o mesmo quelist.Any() exceto que é desnecessariamente mais complexo e a intenção não é clara.


Li ambos como "a lista contém algum item?" Count()tem uma conversão implícita que eu evitaria usar, mas não é claro. O compilador pode otimizá-lo, o que apenas torna a codificação descuidada.
Suncat2000

2

Talvez seja apenas a palavra? Anyé um adjetivo, sem realmente dizer nada. Vindo de Java, eu chamaria issoisNonEmpty que contém um verbo. Um cara do SQL pode preferir EXISTS. Mas talvez Anyse encaixe melhor no sistema C #.

Qualquer que seja a escolha da palavra, uma vez que você se acostume, deve ser bem mais claro. Você perguntaria " more than zeroRestam garrafas de cerveja". Você espera que as one or morepessoas comecem a contá-las antes de responderem "Não, não existe any"?


1
O nome "any" faz sentido quando você pensa em termos de LINQ: Any()é realmente um atalho paraAny(o => true)
BlueRaja - Danny Pflughoeft 4/15

Normalmente, eu não usaria vazio para descrever se um enumerável tinha algo para enumerar. Mas "há qualquer coisa para enumerar" parece natural para mim, e quaisquer obras contra qualquer enumeração.
Andy Andy
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.