C#Linq All&Any在空白数组上工作不同
考虑以下空白数组的LINQ示例:
当Any()返回false因为没有大于零的数字, All()返回true表示所有大于零的数字?
var arr = new int[] { }; Console.WriteLine(arr.Any(n => n > 0)); //false Console.WriteLine(arr.All(n => n > 0)); //true
对我来说似乎合乎逻辑。
-
All:arr所有数字都大于零(表示不存在不大于零的数字)=>true -
Any:arr中是否有大于零的数字=>false
但更重要的是,根据布尔代数 :
arr.All(n => n > 0);
给出true ,因为它应该是逻辑相反的
arr.Any(n => !(n > 0));
这给false (其实这是以上两点说)。
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 element in source) { if (!predicate(element)) return false; } return true; }
它对收集运行foreach 。 如果集合中没有元素,它将跳过这个foreach并返回true。
有趣的是,在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 element in source) { if (predicate(element)) return true; } return false; }
这个cleary显示他们是相反的。
如果列表中没有元素, All 的实现返回true:
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 element in source) { if (!predicate(element)) return false; } return true; // watch this }
这看起来很不直观,但这是如何实现的。
但是文档对于All的返回值是非常清楚的:
如果源序列的每个元素都通过指定谓词中的testing, 或者序列为空 , 则为 true;
一些math观点: Any和All是||广义版本 和&&操作符,就像Sum和Product (不在LINQ中)是+和*概括一样。
广义操作符在空集上操作时返回中立元素的操作。 对于+这是0,因为*这是1所以emptyArray.Product() == 1因为1是*操作的中性元素(对于所有a: a * 1 == a ),对于|| 这是false ( a || false == a ),对于&&这是true ( a || true == a )。
由于这个广义的操作符保持了“原始”操作的相关性,例如Sum: intersect(A,B) == EmptySet; S = union(A,B); S.Sum() == A.Sum() + B.Sum() intersect(A,B) == EmptySet; S = union(A,B); S.Sum() == A.Sum() + B.Sum() intersect(A,B) == EmptySet; S = union(A,B); S.Sum() == A.Sum() + B.Sum() ,即使集合A或B为空,也可以工作。 换句话说,在空集返回中性元素上定义广义运算符在math上是方便的。