C# Any()对IEnumerable状态的影响

C# Any()对IEnumerable状态的影响,c#,linq,ienumerable,C#,Linq,Ienumerable,假设我有一个代码已经在运行,它是这样的 .... .... foreach(object item in enumerator.GetItems(arg1, arg2....) { } .... .... 其中,getItems是抽象类的方法(abstractEnumerator),而getItems返回一个IEnumerable 出现这个问题是因为现在我想在foreach之前使用Any()LINQ扩展来检查枚举是否为空,并且我想确保当IEnumerable到达foreach时,它在IE

假设我有一个代码已经在运行,它是这样的

....
....

foreach(object item in enumerator.GetItems(arg1, arg2....)
{

}

....
....
其中,
getItems
是抽象类的方法(
abstractEnumerator
),而
getItems
返回一个
IEnumerable

出现这个问题是因为现在我想在foreach之前使用Any()LINQ扩展来检查枚举是否为空,并且我想确保当IEnumerable到达foreach时,它在IEnumerable的“状态”中不会发生任何更改,以确保代码的行为与以前完全相同

然而,棘手的部分是,我无法访问abstractEnumerator的实现,因此,我无法访问IEnumerable接口的底层实现

据我所知,接口的Reset方法可以在不做任何操作的情况下返回null。假设abstractEnumerator的实现是由另一家公司的第三方开发人员创建的,因此我无法访问他们的代码

我的问题是,当在for each之前添加Any()时,无论底层实现如何,是否可以确保状态保持不变

根据microsoft在以下任何方面的参考:

'一旦确定结果,源的枚举即停止。'


在这种情况下,我想在第一个元素上停止(基本上我想问的是IEnumerable是否为空),这是否意味着枚举在处理第一个元素之前停止(即,无论实现如何,状态都与未调用Any()相同),或者在处理第一个元素后停止

通常可枚举项本身实际上是无状态的-状态出现在由
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());
}

通常可枚举项本身实际上是无状态的-状态出现在枚举器中,该枚举器由
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());
}

非常感谢你的回答和建议。我考虑过它们(或类似的解决方案),问题是我不认为它们像foreach最初的实现那样干净。但我知道没有别的办法。只是一个问题,如果Reset方法实现正确,那么当我使用LINQ调用Any方法时,迭代器被包装在一个using语句中,因此当我从for each调用它时,枚举器被重置了,对吗?在哪种情况下,枚举数将返回不同的结果?非常感谢您的回答。@user282724:不幸的是,当我们不知道您试图对这些信息做什么时,很难提出其他建议。。。你需要先采取行动吗?之后你希望买多少件?(您可以先将它们复制到
列表中,在该列表中,您可以调用
任何
计数
或列表中您喜欢的任何内容…@user282724:至于您关于
重置的问题-不,这完全不相关。。。并不是在调用
Any
foreach
循环之间重置枚举数。。。将有两个完全独立的迭代器。
Any
foreach
循环都将调用
GetEnumerator()
,每次调用
GetEnumerator()
都应该返回一个独立的迭代器。对于每次返回不同结果的内容-
Enumerable.Range(1100)。例如,选择(x=>GenerateSomeRandomNumber())
。非常感谢您的回答和建议。我考虑过它们(或类似的解决方案),问题是我不认为它们像foreach最初的实现那样干净。但我知道没有别的办法。只是一个问题,如果Reset方法实现正确,那么当我使用LINQ调用Any方法时,迭代器被包装在一个using语句中,因此当我从for each调用它时,枚举器被重置了,对吗?在哪种情况下,枚举数将返回不同的结果?非常感谢您的回答。@user282724:不幸的是,当我们不知道您试图对这些信息做什么时,很难提出其他建议。。。你需要先采取行动吗?之后你希望买多少件?(您可以先将它们复制到
列表中,在该列表中,您可以调用
任何
计数
或列表中您喜欢的任何内容…@user282724:至于您关于
重置的问题-不,这完全不相关。。。并不是在调用
Any
foreach
循环之间重置枚举数。。。将有两个完全独立的迭代器。
Any
foreach
循环都将调用
GetEnumerator()
,每次调用
GetEnumerator()
都应该返回一个独立的迭代器。对于每次返回不同结果的内容-
Enumerable.Range(1100)。例如,选择(x=>GenerateSomeRandomNumber())
。。。