LINQ: 없음 대 모두 없음
종종 제공된 값이 목록의 값과 일치하는지 확인합니다(예: 유효성 검사 시).
if (!acceptedValues.Any(v => v == someValue))
{
// exception logic
}
최근에 저는 ReSharper가 이러한 쿼리를 다음과 같이 단순화할 것을 요청하는 것을 발견했습니다.
if (acceptedValues.All(v => v != someValue))
{
// exception logic
}
분명히, 이것은 논리적으로 동일하고, 아마도 조금 더 읽기 쉬울 것입니다. (만약 당신이 수학을 많이 했다면), 제 질문은 이것이 성능에 타격을 주는 결과를 낳을까 하는 것입니다.
그래야 할 것 같은 느낌이 듭니다..Any()
짧은 시간인 것처럼 들리지만, 반면에..All()
아닌 것처럼 들리지만), 저는 이것을 입증할 것이 없습니다.쿼리가 동일한 문제를 해결할 수 있는지, 아니면 ReSharper가 저를 오해하게 하는지에 대해 더 깊이 알고 있는 사람이 있습니까?
의 구현All
ILSpy에 따르면 (내가 실제로 가서 찾아본 것처럼, "음, 그 방법은 약간..."과 같이 작동한다기 보다는, 만약 우리가 영향보다는 이론에 대해 논의한다면, 나는 할 수 있을 것이다.)
public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (predicate == null)
{
throw Error.ArgumentNull("predicate");
}
foreach (TSource current in source)
{
if (!predicate(current))
{
return false;
}
}
return true;
}
의 구현Any
ILSpy에 따르면:
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (predicate == null)
{
throw Error.ArgumentNull("predicate");
}
foreach (TSource current in source)
{
if (predicate(current))
{
return true;
}
}
return false;
}
물론, 생산된 IL에는 약간의 미묘한 차이가 있을 수 있습니다.하지만 아니요, 없습니다.IL은 거의 동일하지만 술어 일치 시 true를 반환하는 것과 술어 불일치 시 false를 반환하는 것의 명백한 반전에 대한 것입니다.
물론 이것은 객체에 대한 링크입니다.다른 linq 공급자가 다른 공급자보다 훨씬 더 잘 처리할 수도 있지만, 그렇다면 어느 쪽이 더 최적의 구현을 얻었는지는 거의 무작위입니다.
그 규칙은 오직 누군가가 느끼는 것으로 귀결되는 것처럼 보일 것입니다.if(determineSomethingTrue)
보다 간단하고 가독성이 뛰어납니다.if(!determineSomethingFalse)
그리고 공정하게 말하자면, 그들은 제가 종종 발견하는 점에서 약간의 요점을 가지고 있다고 생각합니다.if(!someTest)
동일한 장황성과 복잡성에 대한 대체 테스트가 있을 때 혼란* 우리가 행동하고자 하는 조건에 대해 참으로 반환됩니다.하지만 실제로, 저는 개인적으로 당신이 제시하는 두 가지 대안 중 하나보다 하나를 선호할 만한 것을 찾지 못했고, 술어가 더 복잡하다면 아마도 전자 쪽으로 아주 약간 기울었을 것입니다.
*이해할 수 없는 것처럼 혼란스럽지는 않지만, 이해할 수 없는 결정에 미묘한 이유가 있다고 걱정하는 것처럼 혼란스럽고, "아니, 그들은 방금 그렇게 하기로 결정했습니다. 제가 이 코드를 다시 보고 있었던 이유가 무엇입니까?"라는 것을 깨닫기 위해서는 약간의 정신적인 스킵이 필요합니다.."
다음과 같은 확장 방법을 사용하면 코드를 보다 쉽게 읽을 수 있습니다.
public static bool None<TSource>(this IEnumerable<TSource> source)
{
return !source.Any();
}
public static bool None<TSource>(this IEnumerable<TSource> source,
Func<TSource, bool> predicate)
{
return !source.Any(predicate);
}
당신의 원래의 것 대신에 지금.
if (!acceptedValues.Any(v => v == someValue))
{
// exception logic
}
라고 할 수 있습니다.
if (acceptedValues.None(v => v == someValue))
{
// exception logic
}
가 나온 에 둘 다 수 있기 둘 다 한 성능을 것입니다. - 가 결 후 중 수 때 있 둘 것 입 다 니 가 성 질 동 을 능 한 일 다 에 문 기 지 할 정 거 를 된 열 둘 에 다 eration ▁bothAny()
는 전된술평가첫는번하항서목에째가어로 됩니다.true
그리고.All()
번째 는 어가평 가는첫번항서목에째하로 됩니다.false
.
All
첫 번째 비매치에서 단락이 발생했기 때문에 문제가 없습니다.
한 가지 미묘한 점은
bool allEven = Enumerable.Empty<int>().All(i => i % 2 == 0);
사실입니다.순서에 있는 모든 항목이 짝수입니다.
이 방법에 대한 자세한 내용은 Enumerable 설명서를 참조하십시오.다.
All()
시퀀스의 모든 요소가 조건을 충족하는지 여부를 결정합니다.
Any()
시퀀스의 요소가 조건을 만족하는지 여부를 결정합니다.
var numbers = new[]{1,2,3};
numbers.All(n => n % 2 == 0); // returns false
numbers.Any(n => n % 2 == 0); // returns true
다른 답들도 잘 다루었듯이, 이것은 성능에 관한 것이 아니라 명확성에 관한 것입니다.
두 가지 옵션을 모두 광범위하게 지원합니다.
if (!acceptedValues.Any(v => v == someValue))
{
// exception logic
}
if (acceptedValues.All(v => v != someValue))
{
// exception logic
}
그러나 저는 이것이 더 광범위한 지지를 얻을 수 있다고 생각합니다.
var isValueAccepted = acceptedValues.Any(v => v == someValue);
if (!isValueAccepted)
{
// exception logic
}
어떤 것을 부정하기 전에 부울을 계산하고 이름을 짓는 것만으로도 제 마음은 이것을 많이 이해할 수 있습니다.
Enumerable 소스를 살펴보면 다음과 같은 기능이 구현되었음을 알 수 있습니다.Any
그리고.All
상당히 가깝습니다.
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
foreach (TSource element in source) {
if (predicate(element)) return true;
}
return false;
}
public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
foreach (TSource element in source) {
if (!predicate(element)) return false;
}
return true;
}
유일한 차이점은 부울 부정에 있기 때문에 한 방법이 다른 방법보다 훨씬 빠를 수는 없으므로 잘못된 성능 승리보다 가독성을 선호합니다.
이 링크에 따라
모두 – 하나 이상의 일치 항목을 확인합니다.
모두 – 모두 일치하는지 확인합니다.
언급URL : https://stackoverflow.com/questions/9027530/linq-not-any-vs-all-dont
'programing' 카테고리의 다른 글
Python Script가 매 시간 정확하게 실행되도록 예약 (0) | 2023.05.11 |
---|---|
직렬화 가능 상속 (0) | 2023.05.11 |
이클립스에서 Android용으로 개발: R.java가 재생되지 않음 (0) | 2023.05.11 |
Git push를 사용하여 프로젝트 배포 (0) | 2023.05.11 |
WPF에서 내포된 요소 스타일 지정 (0) | 2023.05.11 |