请考虑以下示例:

List<int> l = [1, 2, 3, 4, 5];
void DoSomethingWith(IEnumerator<int> e) {
    Console.WriteLine(e.MoveNext());
    Console.WriteLine(e.Current);
}
using(var e = l.GetEnumerator()) {
    DoSomethingWith(e);
    DoSomethingWith(e);
}

此代码段输出:

True
1
True
1

我希望

True
1
True
2

因为我传入了相同的枚举数.

为何会是这样呢?

推荐答案

List<T>.GetEnumerator返回的List<T>.Enumeratorstruct,因此通过接口传递它将对其进行装箱(因此,后续调用将使用从当前状态复制的不同实例).例如,以下内容:

using(var e = l.GetEnumerator())
{
    e.MoveNext();
    DoSomethingWith(e);
    DoSomethingWith(e);
}

将打印:

True
2   
True
2   

因此,正如您所看到的,原始枚举数实际上并没有重置.

您可以在using As接口中显式指定类型(因此您将装箱一次并传递枚举器的相同实例):

using(IEnumerator<int> e = l.GetEnumerator())
{
    e.MoveNext();
    DoSomethingWith(e);
    DoSomethingWith(e);
}

或者将方法更改为接受List<int>.Enumerator并将其传递给ref:

void DoSomethingWith(ref List<int>.Enumerator e)
{
    Console.WriteLine(e.MoveNext());
    Console.WriteLine(e.Current);
}

var e = l.GetEnumerator();
DoSomethingWith(ref e);
DoSomethingWith(ref e);

或者通过接口使用集合,因为IEnumerable<T>.GetEnumerator()是显式实现的,装箱将由实现处理:

IEnumerable<int> lAsEn = l;
using(var e = lAsEn.GetEnumerator()) {
    DoSomethingWith(e);
    DoSomethingWith(e);
}

Csharp相关问答推荐

Unity如何在PlayerPrefs中保存数据?

当我使用NET6作为目标框架时,为什么DotNet使用NET8作为MS包?

如果属性名为xyz,我需要使用System.Text.Json修改字符串类型的值""<>

如何在Parall.ForEachAsync中使用CancerationTokenSource

内部接口和类的DI解析

如何从ASP.NET核心MVC视图和Blazor传递数据

C#中浮点数的System.Text.Json序列化问题

如何管理Azure认证客户端响应和证书 fingerprint

将内置的OrderedEumable&Quot;类设置为内部类有什么好处?

什么类型的对象存储在大对象堆(LOH)中

有没有更好的方法来在CosmosDB上插入非id?

Azure函数-在外部启动类中生成配置时出错

这是否比决定是否使用ConfigureAWait(False)更好?

如何在ASP.NET Core 8中获取键控服务词典

处理方法内部过滤与外部过滤

外部应用&&的LINQ;左外部连接&类似于PostgreSQL的查询

实例化列表时的集合表达式是什么?

如何在C#中反序列化Java持续时间?

从列表中跳过和获取条目的优雅方式

C#、Visual Studio代码、调试器、错误处理变量请求.未知错误:0x80131502,