如果反射器是正确的(我倾向于相信它),这就是Any()的实现:
public static bool Any<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return true;
}
return false;
}
根据我的理解,MoveNext()
将基础枚举器移动一个位置,因此多次调用Any()
会对&#34;收缩&#34;产生不利影响。集合。
我尝试使用List<>
重现这一点,但我无法做到这一点,但是,我无法找出List<>
做出不同的解决此问题的方法
验证List<T>
的简单示例适用于多个Any()
调用:
var meh = new List<string> {"1", "2"};
var enumerable = meh.AsEnumerable();
bool any = enumerable.Any(); //true
any = enumerable.Any(); //true
any = enumerable.Any(); //true but isn't it meant to have "moved" the enumerator by two positions already?
any = enumerable.Any(); //true
所以我的问题是:
Any()
确实对Enumerable
List<>
如何绕过它?很抱歉,如果提前这是一个愚蠢的问题。只是我发现非常有趣的东西。
答案 0 :(得分:6)
由于using
语句处理了枚举器,所以它始终从头开始。枚举器也始终从source.GetEnumerator()
创建,不会重复使用。实际上这是.NET源代码,你可以看到here。
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;
}
它枚举序列直到谓词匹配,然后它将被处理掉。
此方法也不使用延迟执行(它缺少yield
关键字)。因此,它总是立即执行。