Muitas vezes, quero verificar se um valor fornecido corresponde a um em uma lista (por exemplo, ao validar):
if (!acceptedValues.Any(v => v == someValue))
{
// exception logic
}
Recentemente, notei o ReSharper me pedindo para simplificar essas consultas para:
if (acceptedValues.All(v => v != someValue))
{
// exception logic
}
Obviamente, isso é logicamente idêntico, talvez um pouco mais legível (se você fez muita matemática), minha pergunta é: isso resulta em um desempenho atingido?
Parece que deveria (ou seja, .Any()
soa como um curto-circuito, enquanto .All()
parece que não), mas não tenho nada para substanciar isso. Alguém tem um conhecimento mais profundo sobre se as consultas resolverão o mesmo ou se o ReSharper está me desviando?
if (!sequence.Any(v => v == true))
. Se você quiser continuar somente se tudo está em conformidade com uma determinada especificação:if (sequence.All(v => v < 10))
.Respostas:
Implementação de
All
acordo com o ILSpy (como na verdade eu fui e olhei, em vez do "bem, esse método funciona um pouco como ..." eu poderia fazer se estivéssemos discutindo a teoria e não o impacto).Implementação de
Any
acordo com ILSpy:Obviamente, pode haver alguma diferença sutil na IL produzida. Mas não, não, não há. O IL é praticamente o mesmo, mas pela inversão óbvia de retornar true na correspondência de predicado versus retornar falso na incompatibilidade de predicado.
Isso é linq-for-objects, é claro. É possível que algum outro provedor de linq trate um muito melhor que o outro, mas se esse for o caso, é bem aleatório qual deles obteve a implementação mais ideal.
Parece que a regra se resume apenas a alguém que se sente
if(determineSomethingTrue)
mais simples e mais legível do queif(!determineSomethingFalse)
. E, para ser sincero, acho que eles têm um certo ponto em que muitas vezes achoif(!someTest)
confuso * quando há um teste alternativo de igual verbosidade e complexidade que retornaria verdadeiro para a condição em que queremos agir. No entanto, realmente, pessoalmente, não encontro nada a favor de uma das outras alternativas que você oferece, e talvez se inclinasse levemente em relação à primeira se o predicado fosse mais complicado.* Não é confuso como em Eu não entendo, mas confuso como em Eu me preocupo que haja alguma razão sutil para a decisão que eu não entendo, e são necessários alguns saltos mentais para perceber que "não, eles apenas decidiram fazer dessa forma, espere o que eu estava olhando para este pedaço de código novamente? ... "
fonte
Any
retornaráfalse
e, portanto!Any
, retornarátrue
, portanto são idênticos.!test.Any(x => x.Key == 3 && x.Value == 1)
esse usoAll
étest.All(x => !(x.Key == 3 && x.Value == 1))
(que é realmente equivalente atest.All(x => x.Key != 3 || x.Value != 1)
).Você pode encontrar esses métodos de extensão para tornar seu código mais legível:
Agora, em vez do seu original
você poderia dizer
fonte
Ambos teriam desempenho idêntico porque ambos param a enumeração após a determinação do resultado -
Any()
no primeiro item que o predicado passado avaliatrue
eAll()
no primeiro item que o predicado avaliafalse
.fonte
All
curto-circuitos no primeiro non-match, por isso não é um problema.Uma área de sutileza é que
É verdade. Todos os itens da sequência são pares.
Para saber mais sobre esse método, consulte a documentação de Enumerable.All .
fonte
bool allEven = !Enumerable.Empty<int>().Any(i => i % 2 != 0)
é verdade.All()
determina se todos os elementos de uma sequência satisfazem uma condição.Any()
determina se algum elemento de uma sequência satisfaz a condição.fonte
De acordo com este link
fonte
Como outras respostas foram bem abordadas: não se trata de desempenho, é de clareza.
Há amplo suporte para as duas opções:
Mas acho que isso pode obter um suporte mais amplo :
Simplesmente calcular o booleano (e nomeá-lo) antes de negar qualquer coisa esclarece muito isso.
fonte
Se você der uma olhada na fonte Enumerable, verá que a implementação de
Any
eAll
é bem próxima:Não há como um método ser significativamente mais rápido que o outro, pois a única diferença está em uma negação booleana; portanto, prefira a legibilidade do que a falsa vitória no desempenho.
fonte