一尘不染

LINQ:不是任何人都不是所有人

c#

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

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

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

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

显然,这在逻辑上是相同的,也许可读性更高(如果您完成了许多数学运算),我的问题是:这会导致性能下降吗?

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


阅读 222

收藏
2020-05-19

共1个答案

一尘不染

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)当存在相同的冗长性和复杂性的替代测试会针对我们要采取的条件返回真值时,我经常会感到困惑*。但是,实际上,我个人没有发现要比您提供的两种选择中的任何一种更偏爱的,如果谓词更复杂,也许会稍微偏向于前者。

*不要因为我不明白而感到困惑,但是因为担心我不理解的决定有一些微妙的原因而感到困惑,并且需要一些思想上的跳跃才能意识到“不,他们只是决定做这样,等我又在看这段代码吗?…”

2020-05-19