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-for-objects입니다. 다른 linq 제공자는 다른 linq 제공자가 다른 것보다 하나를 더 잘 처리 할 수 있지만,이 경우 더 최적의 구현을 가진 것은 무작위입니다.
It would seem that the rule comes down solely to someone feeling that if(determineSomethingTrue)
is simpler and more readable than if(!determineSomethingFalse)
. And in fairness, I think they've a bit of a point in that I often find if(!someTest)
confusing* when there's an alternative test of equal verbosity and complexity that would return true for the condition we want to act upon. Yet really, I personally find nothing to favour one over the other of the two alternatives you give, and would perhaps lean very slightly toward the former if the predicate were more complicated.
* 나는 이해하지 못하는 것처럼 혼란스럽지 않지만, 나는 이해하지 못하는 결정에 미묘한 이유가 있다고 걱정하고, "아니, 그들은 단지 그런 식으로 기다렸다가 다시이 코드를보고 있던 것이 무엇입니까? ... "
이러한 확장 방법을 사용하면 코드를 더 읽기 쉽게 만들 수 있습니다.
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
}
- 둘 다 결과 후 모두 정지 열거 판단 할 수 있기 때문에 동일한 성능 것이다 Any()
첫 번째 항목에 전달 된 술어 평가합니다로 true
와 All()
의 술어 평가하여 첫 번째 항목에를 false
.
All
첫 번째 비 일치에 단락이 발생하므로 문제가되지 않습니다.
미묘의 한 영역은
bool allEven = Enumerable.Empty<int>().All(i => i % 2 == 0);
사실이다. 시퀀스의 모든 항목이 균일합니다.
이 방법에 대한 자세한 내용은 Enumerable.All 설명서를 참조하십시오 .
이 링크 에 따르면
모두 – 하나 이상의 일치를 확인합니다
모두 – 모두 일치하는지 확인
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
'IT' 카테고리의 다른 글
DOM 요소를 jQuery 요소로 변환하려면 어떻게해야합니까? (0) | 2020.03.31 |
---|---|
find 명령으로 정규식을 사용하는 방법은 무엇입니까? (0) | 2020.03.31 |
getattr ()이란 무엇이며 어떻게 사용합니까? (0) | 2020.03.31 |
C / C ++ 헤더 파일 순서 포함 (0) | 2020.03.31 |
스칼라 컨텍스트와 뷰 범위는 무엇입니까? (0) | 2020.03.31 |