所以我今天遇到了这样一种情况:一些生产代码之所以失败,正是因为有一种方法的执行与msdn中所记录的完全相同。我很遗憾没有阅读文档。然而,我仍然在绞尽脑汁地思考它为什么会这样做,即使是"按设计",因为这种行为与我预期的完全相反(以及其他已知的行为),因此似乎违反了最不令人惊讶的原则。
All()方法允许您提供一个谓词(例如lambda表达式)来测试IQueryable,返回一个布尔值,该值指示所有集合成员是否与测试匹配。到现在为止,一直都还不错。这就是奇怪的地方。如果集合为空,All()也返回true。在我看来,这完全是倒退的,原因如下:
- 如果集合为空,那么这样的测试最多是未定义的。如果我的车道是空的,我不能断言所有停在那里的车都是红色的。有了这种行为,在一条空车道上,所有停在那里的车都有红蓝相间的棋盘格——所有这些表达式都会返回真值。
- 对于任何熟悉SQL概念的人来说,这是空的!=空,这是意外行为。
- Any()方法的行为与预期一致,并且(正确地)返回false,因为它没有任何与谓词匹配的成员。
所以我的问题是,为什么All()的行为是这样的?它能解决什么问题?这是否违反了最小惊喜原则?
我将这个问题标记为.NET 3.5,尽管这种行为也适用于.NET 4.0。
编辑好了,所以我掌握了这方面的逻辑,就像杰森和你们其他人所做的那样。诚然,一个空的集合有点像一个边缘案例。我想我的问题根源于这场斗争,仅仅因为某些事情是合乎逻辑的,并不意味着如果你没有处于正确的心态中,这就必然是有意义的。
- 我要从你的帖子中删除[EDOCX1[0]标签,这不是一个主观问题。这些是逻辑的规则,它们非常合乎逻辑。一旦你对这些想法有了足够的练习,它们就会变得直观起来。
- "它们变得直观了……"是的,我在大学里学过逻辑表等。15年前。:)
- 我的想法是,如果你在练习什么的话,我对它是否具有"实际"意义有不同的看法。如果你关心的是"一切"的意思,"没有相反的实例",那么硬逻辑的定义完全适合你。但对于许多问题,我们可能会寻找"没有相反的例子,至少有一个我想要的场景的实例"。这实际上是两个声明,所以在LINQ中有两个不同的条件。计数(条件)>0和全部(条件)。我真的很好奇是否有一个聪明的方法让它成为一个。
If my driveway is empty, I cannot assert that all cars parked there are red.
号
考虑以下陈述。
S1: My driveway is empty.
S2: All the cars parked in my driveway are red.
号
我声称S1表示S2。也就是说,S1 => S2的说法是正确的。我会证明它的否定是错误的。在这种情况下,S1 => S2的否定是S1 ^ ~S2;这是因为只有当S1为真,S2为假时,S1 => S2才是假的。S2的否定是什么?它是
~S2: There exists a car parked in my driveway that is not red.
号
S1 ^ ~S2的真实价值是多少?我们把它写出来吧
S1 ^ ~S2: My driveway is empty and there exists a car parked in my driveway that is not red.
号
只有当S1和~S2都是真的,S1 ^ ~S2才是真的。但是S1说我的车道是空的,S2说我的车道上有一辆车。我的车道不能既空又有车。因此,S1和~S2都不可能是真的。因此,S1 ^ ~S2是假的,所以它的否定S1 => S2是真的。
因此,如果你的车道是空的,你可以断言所有停在那里的车都是红色的。
现在让我们考虑一个IEnumerable elements和一个Predicate p。假设elements是空的。我们希望发现
1
| bool b = elements.All(x => p(x)); |
让我们考虑一下它的否定
1
| bool notb = elements.Any(x => !p(x)); |
号
为了使notb为真,elements中必须至少有一个x,!p(x)为真。但是elements是空的,所以不可能找到一个x是真的。因此,notb不能是真的,所以它一定是假的。由于notb是假的,它的否定是真的。因此,如果elements为空,b为真,elements.All(x => p(x))为真。
还有一种方法可以考虑这个问题。如果在elements中的所有x找不到任何虚假的,则谓词p为真。但如果elements中没有项目,就不可能找到任何虚假项目。因此,对于一个空的集合elements,p对于elements中的所有x都是正确的。
现在,当elements是一个空的IEnumerable和p是一个如上所述的Predicate时,elements.Any(x => p(x))怎么办?我们已经知道结果是错误的,因为我们知道它的否定是正确的,但是让我们通过它来推理,直觉是有价值的。为了使elements.Any(x => p(x))为真,elements中必须至少有一个x,p(x)为真。但是如果elements中没有x的话,就不可能找到p(x)是真的x。因此,如果elements为空,则elements.Any(x => p(x))为假。
最后,本文对当s是string的非空实例时,为什么s.StartsWith(String.Empty)是真的作了相关解释:
- 你的语义学支持了……但它还是有点不自然。
- 计算机科学和逻辑依赖于语义学,事实上,它们在意义上有着千差万别的区别。
- 问题是,错误的陈述并不是事实,只是因为你不能证明它是错误的。展品1:飞行意大利面怪兽。它至多是不确定的。说"我车道上所有的车都是红色的"在语义上是错误的,因为这意味着在你的车道上至少有一辆红色的车。因此,实现的行为确实符合单词"all"的含义。用词来命名一个方法的全部目的是给它的读者赋予意义。该方法的名称是似是而非的,最好命名为Method1。
如果返回true的项目数与所有项目数相同,则返回true。就这么简单:
1
| Driveway.Cars(a => a.Red).Count() == Driveway.Cars.Count() |
相关说明:为什么"abcd".startswith(")返回true?
"If the collection is empty, a test
like this is, at best, undefined. If
my driveway is empty, I cannot assert
that all cars parked there are red."
号
是的,你可以。
为了证明我错了,让我看看你空车道上一辆不是红色的车。
For anyone familiar with the SQL notion that NULL != NULL, this is unexpected behavior.
号
这是SQL的一个怪癖(不完全正确:NULL = NULL和NULL <> NULL都是未定义的,两者都不会匹配任何行)。
- 所以让我看看我空车道上的一辆车,它不是红色的,它是红色的。
- 这两种说法都是正确的。(1)车道上没有红色的车,(2)车道上没有红色的车。没有矛盾。
- 我想这就是我所得到的-从整体上脱离=>!(!任何)问题,从没有不匹配的元素,但也没有匹配的元素的角度来看,测试可以是真的也可以是假的。
Any()和All()只是普通数学运算符的实现?(即"存在的四元证明者"或"存在的四元证明者")和?(以下简称"通用quartifier"或"for all")。
"any"表示存在谓词为真的项。对于空集合,这将是错误的。
"全部"表示不存在谓词为假的项。对于空集合,这始终是正确的。
我认为这是有道理的。在逻辑上,对所有事物的补充是不存在的。因为一切都像江户记1(7)。存在着类似于Any()。
因此,IQueryable.All()相当于!IQueryable.Any()。如果您的IQueryable为空,那么根据msdn-doc,两者都返回true。
- iqueryable.all()不等价于!iqueryable.any()。您还需要否定谓词。
- 啊,是的,你是对的。
因为对一个空集合的任何命题都是一个空洞的真理。
你会在数学或计算机科学的其他领域经常发现这种行为。
如果范围无效(从0到-1的总和),Math中的sum运算符将返回0(零元素+)。multipyl运算符将返回1(用于乘法的中性元素)。
现在,如果您有布尔表达式,它非常相似:或的中性元素是false(a OR false = a),而和的中性元素是true。
现在关于Linq的ANY和ALL:它们类似于:
1 2
| ANY = a OR b OR c OR d ...
ALL = a AND b AND c AND d ... |
号
所以,如果你有数学/cs背景,这种行为就是"你所期望的"。
返回true也是合乎逻辑的。你有两句话:"有车吗?""它是红色的吗?"如果第一个语句是false,那么第二个语句是什么并不重要,结果是modus ponens生成的true。
All(x => x.Predicate)是Any(x => !x.Predicate)的对立面("所有汽车都是红色的吗?"与"有没有不红色的车?"相反吗?.
Any(x => !x.Predicate)返回false用于空集合(对于"any"的共同理解,这似乎是自然的)。
因此,对于空的托收,All(x => x.Predicate)应该(并且确实)返回true。
它非常类似于数字0的基本概念。即使它代表着缺席的存在,它仍然拥有并代表着一个价值。iqueryable.all()应返回true,因为它将成功返回集合的所有成员。如果集合为空,则函数不会返回任何成员,但不会返回任何成员,因为函数无法返回任何成员。这仅仅是因为没有成员可以返回。也就是说,为什么iqueryable.all()必须经历失败,因为缺乏集合的支持?它是自愿的,它是有能力的……它是有能力的。在我看来,这些收藏品没法维持他们的交易…
http://mathforum.org/dr.math/faq/faq.divideby0.html
false表示查询没有返回任何结果,即使没有谓词。这只是一个不完整的方式来说明什么目的地张贴当我打字这个。