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 

对我来说似乎合乎逻辑。

  • Allarr 所有数字都大于零(表示不存在大于零的数字)=> true
  • Anyarr中是否有大于零的数字=> 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观点: AnyAll||广义版本 和&&操作符,就像SumProduct (不在LINQ中)是+*概括一样。

广义操作符在空集上操作时返回中立元素的操作。 对于+这是0,因为*这是1所以emptyArray.Product() == 1因为1是*操作的中性元素(对于所有a: a * 1 == a ),对于|| 这是falsea || false == a ),对于&&这是truea || 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() ,即使集合AB为空,也可以工作。 换句话说,在空集返回中性元素上定义广义运算符在math上是方便的。