假设我的代码已经在运行,就像这样
....
....
foreach(object item in enumerator.GetItems(arg1, arg2....)
{
}
....
....
其中getItems
是抽象类的方法(abstractEnumerator
),getItems
返回IEnumerable<object>
。
问题出现了,因为现在我想在foreach之前使用Any()LINQ扩展来检查枚举是否为空,并且我想确保它在IEnumerable的所有“状态”时都不会改变它到达foreach,以确保代码的行为与以前一样。
然而,棘手的部分是,我无法访问abstractEnumerator的实现,因此,我无法访问IEnumerable接口的底层实现。
据我所知,接口的Reset方法可以返回null而不做任何事情。想象一下,abstractEnumerator的实现是由另一家公司的第三方开发人员创建的,所以我无法访问他们的代码。
我的问题是,如果我可以确定状态将保持不变,当在for之前添加Any()时,无论底层实现如何。
根据Any上的微软参考:
'只要可以确定结果,就会停止源的枚举。 “
在这种情况下,我想停在第一个元素上(基本上我要问的是IEnumerable是否为空),这是否意味着枚举在之前停止 > 处理第一个元素(即状态与未调用Any()相同,无论实现如何),或者在 处理之后停止 第一个元素?
答案 0 :(得分:6)
通常,enumerables本身实际上是无状态的 - 状态来自GetEnumerator()
返回的枚举器。但是,如果你想避免两次调用GetEnumerator()
(当然每次都可以很容易地给出不同的结果),最简单的方法就是记住你是否看到了任何元素:
bool any = false;
foreach (var element in GetItems(...))
{
any = true;
}
if (any)
{
// whatever
}
当然,如果你想在第一次迭代之前采取行动,那将无济于事。如果你想这样做,你可以自己使用迭代器:
using (var iterator = GetItems(...).GetEnumerator())
{
if (iterator.MoveNext())
{
// Take your "pre-iteration" action
}
do
{
var item = iterator.Current;
// Use the item
} while (iterator.MoveNext());
}