为什么 Enumerable.All 对于空序列返回 true?

发布于 2024-12-11 21:07:23 字数 254 浏览 0 评论 0原文

var strs = new Collection<string>();
bool b = strs.All(str => str == "ABC");

该代码创建一个空字符串集合,然后尝试确定该集合中的所有元素是否都是“ABC”。 如果运行它,b 将为 true。

但该集合中甚至没有任何元素,更不用说任何等于“ABC”的元素了。

这是一个错误,还是有合理的解释?

var strs = new Collection<string>();
bool b = strs.All(str => str == "ABC");

The code creates an empty collection of string, then tries to determine if all the elements in the collection are "ABC".
If you run it, b will be true.

But the collection does not even have any elements in it, let alone any elements that equal to "ABC".

Is this a bug, or is there a reasonable explanation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

别闹i 2024-12-18 21:07:23

这当然不是一个错误。它的行为完全如文档所述

如果源序列的每个元素都通过指定谓词中的测试,则为 true,或者如果序列为空;否则为假。

现在你可以争论它是否应该以这种方式工作(对我来说这似乎很好;序列的每个元素都符合谓词),但是首先要检查 > 在你问某件事是否是错误之前,先看一下文档。 (一旦方法的行为与您预期的不同,这是首先要检查的事情。)

It's certainly not a bug. It's behaving exactly as documented:

true if every element of the source sequence passes the test in the specified predicate, or if the sequence is empty; otherwise, false.

Now you can argue about whether or not it should work that way (it seems fine to me; every element of the sequence conforms to the predicate) but the very first thing to check before you ask whether something is a bug, is the documentation. (It's the first thing to check as soon as a method behaves in a way other than what you expected.)

驱逐舰岛风号 2024-12-18 21:07:23

All 要求谓词对于序列的所有元素都为 true。文档中明确说明了这一点。如果您将 All 视为每个元素的谓词结果之间的逻辑“与”,那么这也是唯一有意义的事情。您为空序列得出的 true 是“and”运算的单位元素。同样,从 Any 获得的空序列的 false 是逻辑“或”的标识。

如果您将 All 视为“序列中没有不存在的元素”,这可能更有意义。

All requires the predicate to be true for all elements of the sequence. This is explicitly stated in the documentation. It's also the only thing that makes sense if you think of All as being like a logical "and" between the predicate's results for each element. The true you're getting out for the empty sequence is the identity element of the "and" operation. Likewise, the false you get from Any for the empty sequence is the identity for logical "or".

If you think of All as "there are no elements in the sequence that are not", this might make more sense.

紫轩蝶泪 2024-12-18 21:07:23

它是true,因为没有任何条件(没有条件)使它false

文档可能对此进行了解释。 (Jon Skeet 几年前也提到过)

对于空集返回 falseAny (与 All 相反)也是如此。

编辑:

您可以想象 All 在语义上的实现与以下内容相同:

foreach (var e in elems)
{
  if (!cond(e))
    return false;
}
return true; // no escape from loop

It is true, as nothing (no condition) makes it false.

The docs probably explain it. (Jon Skeet also mentioned something a few years back)

Same goes for Any (the opposite of All) returning false for empty sets.

Edit:

You can imagine All to be implemented semantically the same as:

foreach (var e in elems)
{
  if (!cond(e))
    return false;
}
return true; // no escape from loop
笑红尘 2024-12-18 21:07:23

这里的大多数答案似乎都是“因为这就是定义的”。但这样定义也是有逻辑原因的。

定义函数时,您希望函数尽可能通用,以便可以应用于尽可能多的情况。举例来说,我想定义 Sum 函数,它返回列表中所有数字的总和。当列表为空时它应该返回什么?如果您要返回任意数字 x,则可以将该函数定义为:

  1. 返回给定列表中所有数字之和的函数,或者如果满足以下条件,则返回 x:列表为空。

但如果 x 为零,您也可以将其定义为

  1. 返回 x 加上给定数字的函数。

请注意,定义 2 隐含定义 1,但当 x 不为零时,1 并不隐含 2,这本身就足以有理由选择 2 而不是 1。但还要注意 2 更优雅< /em> 就其本身而言,比 1 更通用。就像将聚光灯放置得更远,以便照亮更大的区域。实际上要大得多。我自己不是数学家,但我确信他们会发现定义 2 和其他数学概念之间存在大量联系,但当 x 不为零时,与定义 1 的联系就不那么多了。

一般来说,您可以并且很可能希望返回 身份元素(离开当您有一个函数对一组元素应用二元运算符并且该集合为空时,其他操作数不变)。这与当列表为空时 Product 函数返回 1 的原因相同(请注意,您可以将定义 2 中的“x plus”替换为“one times”) 。与当列表为空时 All(可以被认为是逻辑 AND 运算符的重复应用)将返回 true 的原因相同(p & ;& true 相当于 p),同样的原因 Any(OR 运算符)将返回 false

Most answers here seem to go along the lines of "because that's how is defined". But there is also a logical reason why is defined this way.

When defining a function, you want your function to be as general as possible, such that it can be applied to the largest possible number of cases. Say, for instance, that I want to define the Sum function, which returns the sum of all the numbers in a list. What should it return when the list is empty? If you'd return an arbitrary number x, you'd define the function as the:

  1. Function that returns the sum of all numbers in the given list, or x if the list is empty.

But if x is zero, you can also define it as the

  1. Function that returns x plus the given numbers.

Note that definition 2 implies definition 1, but 1 does not imply 2 when x is not zero, which by itself is enough reason to pick 2 over 1. But also note 2 is more elegant and, in its own right, more general than 1. Is like placing a spotlight farther away so that it lightens a larger area. A lot larger actually. I'm not a mathematician myself but I'm sure they'll find a ton of connections between definition 2 and other mathematical concepts, but not so many related to definition 1 when x is not zero.

In general, you can, and most likely want to return the identity element (the one that leaves the other operand unchanged) whenever you have a function that applies a binary operator over a set of elements and the set is empty. This is the same reason a Product function will return 1 when the list is empty (note that you could just replace "x plus" with "one times" in definition 2). And is the same reason All (which can be thought of as the repeated application of the logical AND operator) will return true when the list is empty (p && true is equivalent to p), and the same reason Any (the OR operator) will return false.

子栖 2024-12-18 21:07:23

该方法循环遍历所有元素,直到找到不满足条件的元素,或者找不到失败的元素。如果没有失败,则返回 true。

因此,如果没有元素,则返回 true (因为没有失败的元素)

The method cycles through all elements until it finds one that does not satisfy the condition, or finds none that fail. If none fail, true is returned.

So, if there are no elements, true is returned (since there were none that failed)

開玄 2024-12-18 21:07:23

这是一个可以完成OP想要做的事情的扩展:

static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool mustExist)
{
    foreach (var e in source)
    {
        if (!predicate(e))
            return false;
        mustExist = false;
    }
    return !mustExist;
}

...正如其他人已经指出的那样,这不是一个错误,而是有详细记录的预期行为。

如果不想编写新扩展,另一种解决方案是:

strs.DefaultIfEmpty().All(str => str == "ABC");

PS:如果寻找默认值本身,上述方法不起作用!
(对于字符串来说,这将为空。)
在这种情况下,它会变得不那么优雅,类似于:

strs.DefaultIfEmpty(string.Empty).All(str => str == null);

如果您可以多次枚举,最简单的解决方案是:

strs.All(predicate) && strs.Any();

即简单地在实际存在 any 元素之后添加一个检查。

Here is an extension that can do what OP wanted to do:

static bool All<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool mustExist)
{
    foreach (var e in source)
    {
        if (!predicate(e))
            return false;
        mustExist = false;
    }
    return !mustExist;
}

...and as others have pointed out already this is not a bug but well-documented intended behavior.

An alternative solution if one does not wish to write a new extension is:

strs.DefaultIfEmpty().All(str => str == "ABC");

PS: The above does not work if looking for the default value itself!
(Which for strings would be null.)
In such cases it becomes less elegant with something similar to:

strs.DefaultIfEmpty(string.Empty).All(str => str == null);

If you can enumerate more than once the easiest solution is:

strs.All(predicate) && strs.Any();

i.e simply add a check after that there actually were any element.

辞旧 2024-12-18 21:07:23

将实施放在一边。是否属实真的很重要吗?查看是否有一些代码可以迭代可枚举并执行一些代码。如果 All() 为 true,那么该代码仍然不会运行,因为可枚举中没有任何元素。

var hungryDogs = Enumerable.Empty<Dog>();
bool allAreHungry = hungryDogs.All(d=>d.Hungry);    
if (allAreHungry)
    foreach (Dog dog in hungryDogs)
         dog.Feed(biscuits); <--- this line will not run anyway.

Keeping the implementation aside. Does it really matter if it is true? See if you have some code which iterates over the enumerable and executes some code. if All() is true then that code is still not going to run since the enumerable doesn't have any elements in it.

var hungryDogs = Enumerable.Empty<Dog>();
bool allAreHungry = hungryDogs.All(d=>d.Hungry);    
if (allAreHungry)
    foreach (Dog dog in hungryDogs)
         dog.Feed(biscuits); <--- this line will not run anyway.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文