Any()对IEnumerable

时间:2015-10-12 23:48:54

标签: c# linq ienumerable

假设我的代码已经在运行,就像这样

....
....

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()相同,无论实现如何),或者在 处理之后停止 第一个元素?

1 个答案:

答案 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());
}