C# LINQ:不是任何还是所有都不要

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9027530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 05:39:41  来源:igfitidea点击:

LINQ: Not Any vs All Don't

c#.netperformancelinqresharper

提问by Mark

Often I want to check if a provided value matches one in a list (e.g. when validating):

我经常想检查提供的值是否与列表中的值匹配(例如在验证时):

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

Recently, I've noticed ReSharper asking me to simplify these queries to:

最近,我注意到 ReSharper 要求我将这些查询简化为:

if (acceptedValues.All(v => v != someValue))
{
    // exception logic
}

Obviously, this is logically identical, perhaps slightly more readable (if you've done a lot of mathematics), my question is: does this result in a performance hit?

显然,这在逻辑上是相同的,可能稍微更具可读性(如果你已经做了很多数学),我的问题是:这会导致性能下降吗?

It feels like it should (i.e. .Any()sounds like it short-circuits, whereas .All()sounds like it does not), but I have nothing to substantiate this. Does anyone have deeper knowledge as to whether the queries will resolve the same, or whether ReSharper is leading me astray?

感觉它应该(即.Any()听起来像是短路,而.All()听起来它没有),但我没有任何证据证明这一点。有没有人对查询是否会解决相同的问题有更深入的了解,或者 ReSharper 是否让我误入歧途?

采纳答案by Jon Hanna

Implementation of Allaccording to ILSpy (as in I actually went and looked, rather than the "well, that method works a bit like ..." I might do if we were discussing the theory rather than the impact).

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;
}

Implementation of Anyaccording to ILSpy:

实施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;
}

Of course, there could be some subtle difference in the IL produced. But no, no there isn't. The IL is pretty much the same but for the obvious inversion of returning true on predicate match versus returning false on predicate mismatch.

当然,产生的 IL 可能会有一些细微的差异。但不,不,没有。IL 几乎相同,但对于谓词匹配时返回 true 与谓词不匹配时返回 false 的明显反转。

This is linq-for-objects only of course. It's possible that some other linq provider treats one much better than the other, but then if that was the case, it's pretty much random which one got the more optimal implementation.

这当然只是 linq-for-objects。其他一些 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.

似乎该规则完全归结为某人感觉if(determineSomethingTrue)if(!determineSomethingFalse). 公平地说,我认为他们有点意思,因为if(!someTest)当存在对我们想要采取行动的条件返回 true 的同等冗长和复杂性的替代测试时,我经常感到困惑*。然而,实际上,我个人认为没有什么比你给出的两种选择中的另一种更喜欢的了,如果谓词更复杂,我可能会略微倾向于前者。

*Not confusing as in I don't understand, but confusing as in I worry that there's some subtle reason for the decision that I don't understand, and it takes a few mental skips to realise that "no, they just decided to do it that way, wait what was I looking at this bit of code for again?..."

*不是因为我不明白而令人困惑,而是因为我担心有一些我不理解的决定的微妙原因而令人困惑,并且需要进行一些心理跳跃才能意识到“不,他们只是决定做就这样,等等,我又在看这段代码是为了什么?......”

回答by Anthony Pegram

Allshort circuits on the first non-match, so it's not a problem.

All第一次不匹配时短路,所以这不是问题。

One area of subtlety is that

一个微妙的领域是

 bool allEven = Enumerable.Empty<int>().All(i => i % 2 == 0); 

Is true. All of the items in the sequence are even.

是真的。序列中的所有项目都是偶数。

For more on this method, consult the documentation for Enumerable.All.

有关此方法的更多信息,请参阅Enumerable.All的文档。

回答by BrokenGlass

Both would have identical performance because both stop enumeration after the outcome can be determined - Any()on the first item the passed predicate evaluates to trueand All()on the first item the predicate evaluates to false.

双方将具有相同的性能,因为结果后都停止计数可确定-Any()第一个项目所传递的谓词为trueAll()第一项的断言求false

回答by AakashM

You might find these extension methods make your code more readable:

您可能会发现这些扩展方法使您的代码更具可读性:

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);
}

Now instead of your original

现在而不是你原来的

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

you could say

你可以说

if (acceptedValues.None(v => v == someValue))
{
    // exception logic
}

回答by rcarvalhoxavier

According to this link

根据这个链接

Any – Checks for at least one match

All – Checks that all match

Any – 检查至少一场比赛

全部 - 检查所有匹配

回答by emy

All()determines whether all elements of a sequence satisfy a condition.
Any()determines whether any element of a sequence satisfies the condition.

All()确定序列的所有元素是否都满足条件。
Any()确定序列的任何元素是否满足条件。

var numbers = new[]{1,2,3};

numbers.All(n => n % 2 == 0); // returns false
numbers.Any(n => n % 2 == 0); // returns true

回答by Michael Haren

As other answers have well covered: this is not about performance, it's about clarity.

正如其他答案所涵盖的那样:这与性能无关,而与清晰度有关。

There's wide support for both of your options:

您的两种选择都得到广泛支持:

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

if (acceptedValues.All(v => v != someValue))
{
    // exception logic
}

But I think this might achieve broader support:

但我认为这可能会获得更广泛的支持

var isValueAccepted = acceptedValues.Any(v => v == someValue);
if (!isValueAccepted)
{
    // exception logic
}

Simply computing the boolean (and naming it) before negating anything clears this up a lot in my mind.

在否定任何东西之前简单地计算布尔值(并命名它)在我的脑海中清除了很多。

回答by Thomas Ayoub

If you take a look at the Enumerable sourceyou'll see that the implementation of Anyand Allis quite close:

如果你在看看可枚举源你会看到的实施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;
}

There is no way that one method be significantly faster than the other since the only difference lies in a boolean negation, so prefer readability over false performance win.

一种方法不可能比另一种方法快得多,因为唯一的区别在于布尔否定,所以更喜欢可读性而不是错误的性能胜利。