为什么 IQueryable.All() 在空集合上返回 true?

2024-02-02

所以我今天遇到了一种情况,一些生产代码失败正是因为一个方法的执行完全按照记录在 MSDN 中 http://msdn.microsoft.com/en-us/library/bb534754.aspx。为我没有阅读文档而感到羞耻。然而,我仍然摸不着头脑why它的行为方式是这样的,即使是“故意设计的”,因为这种行为与我的预期(以及其他已知的行为)完全相反,因此似乎违反了最小惊喜原则。

The All()方法允许您提供谓词(例如 lambda 表达式)来测试IQueryable,返回一个布尔值,指示所有集合成员是否与测试匹配。到目前为止,一切都很好。这就是奇怪的地方。All()也返回true如果集合为空。这对我来说似乎完全倒退,原因如下:

  • 如果集合为空,那么这样的测试充其量是未定义的。如果我的车道是空的,我不能断言停在那里的所有汽车都是红色的。通过这种行为,在空车道上停放的所有汽车都是红色、蓝色和棋盘 - 所有这些表达式都将返回 true。
  • 对于任何熟悉 NULL != NULL SQL 概念的人来说,这是意想不到的行为。
  • The Any()方法的行为符合预期,并且(正确地)返回 false,因为它没有任何与谓词匹配的成员。

所以我的问题是,为什么All()这样做吗?它解决什么问题?这是否违反了最小意外原则?

我将此问题标记为 .NET 3.5,尽管该行为也适用于 .NET 4.0。

EDIT好的,我掌握了这方面的逻辑,正如杰森和你们其他人出色地阐述的那样。诚然,空集合是一种边缘情况。我想我的问题源于这样的斗争,仅仅因为某件事是logical并不意味着它必然使sense如果你的心态不正确。


如果我的车道是空的,我不能断言停在那里的所有汽车都是红色的。

考虑以下陈述。

S1: 我的车道是空的。

S2:停在我车道上的所有汽车都是红色的。

我声称S1暗示S2。也就是说,声明S1 => S2是真的。我将通过证明它的否定是错误的来做到这一点。在这种情况下,否定S1 => S2 is S1 ^ ~S2;这是因为S1 => S2仅当S1是真的并且S2是假的。什么是否定S2? It is

~S2:我的车道上停着一辆不是红色的汽车。

的真值是多少S1 ^ ~S2?我们把它写出来

S1 ^ ~S2:我的车道是空的,并且我的车道上停着一辆不是红色的汽车。

唯一的办法就是S1 ^ ~S2可能是真的,如果两者都是S1 and ~S2是真的。但S1说我的车道是空的并且S2说我的车道上有一辆车。我的车道不能既是空的又包含汽车。因此,不可能S1 and ~S2两者都是真实的。所以,S1 ^ ~S2是假的,所以它的否定S1 => S2是真的。

因此,如果您的车道是空的,您可以断言停在那里的所有汽车都是红色的。

所以现在让我们考虑一个IEnumerable<T> elements and a Predicate<T> p。让我们假设elements是空的。我们希望发现的价值

bool b = elements.All(x => p(x));

让我们考虑一下它的否定

bool notb = elements.Any(x => !p(x));

For notb为真,必须至少有一个x in elements为此!p(x)是真的。但elements是空的,所以不可能找到x为此!p(x)是真的。所以notb不可能是真的,所以它一定是假的。自从notb为假,其否定为真。所以b是真的并且elements.All(x => p(x))必须为真,如果elements是空的。

这是思考这个问题的另一种方式。谓词p为真,如果对于all x in elements你找不到any这是错误的。但如果里面没有任何物品elements那么就不可能找到any这是错误的。因此,对于一个空集合elements, p是真的all x in elements

现在,怎么样elements.Any(x => p(x)) when elements是一个空的IEnumerable<T> and p is a Predicate<T>如上?我们已经知道结果将是假的,因为我们知道它的否定是真的,但无论如何让我们通过它进行推理;直觉是有价值的。为了elements.Any(x => p(x))为真必须至少有一个x in elements为此p(x)是真的。但如果没有的话any x in elements不可能找到any x为此p(x)是真的。所以,elements.Any(x => p(x))为假,如果elements是空的。

最后,这是一个相关解释 https://stackoverflow.com/questions/145509/why-does-abcd-startswith-return-true/390801#390801 on why s.StartsWith(String.Empty)s是一个非空实例string:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 IQueryable.All() 在空集合上返回 true? 的相关文章

随机推荐