通常我想检查提供的值是否与列表中的值匹配(例如在验证时):
if (!acceptedValues.Any(v => v == someValue)) { // exception logic }
最近,我注意到 ReSharper 要求我将这些查询简化为:
if (acceptedValues.All(v => v != someValue)) { // exception logic }
显然,这在逻辑上是相同的,也许更具可读性(如果你做了很多数学),我的问题是:这会导致性能下降吗?
感觉它应该(即.Any()听起来像是短路,而.All()听起来却没有),但我没有什么可以证实这一点。有没有人更深入地了解查询是否会解决相同的问题,或者 ReSharper 是否让我误入歧途?
.Any()
.All()
根据 ILSpy实施All(正如我实际上去查看的那样,而不是“好吧,该方法有点像……”,如果我们讨论的是理论而不是影响,我可能会这样做)。
All
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的实现:
Any
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 提供者可能会比另一个更好地对待一个,但如果是这种情况,那么哪个获得了更优化的实现几乎是随机的。
似乎该规则仅归结为某人感觉if(determineSomethingTrue)比if(!determineSomethingFalse). 公平地说,我认为他们有点意思,我经常会if(!someTest)感到困惑*,当有另一种同等冗长和复杂性的测试对于我们想要采取行动的条件返回 true 时。然而,实际上,我个人认为没有什么比你给出的两种选择中的另一种更受欢迎的了,如果谓词更复杂,我可能会略微倾向于前者。
if(determineSomethingTrue)
if(!determineSomethingFalse)
if(!someTest)
*不是像我不明白那样令人困惑,而是像我担心我不明白的决定有一些微妙的原因一样令人困惑,并且需要一些精神上的跳跃才能意识到“不,他们只是决定这样做就这样,等我再看这段代码是为了什么?…”