运行 无法枚举 IAsyncEnumerable 两次?
Run enumeration of IAsyncEnumerable twice not possible?
运行 枚举 IAsyncEnumerable
两次不可能?
一旦 CountAsync
变为 运行,await foreach
将不会枚举任何项目。为什么?
AsyncEnumerator
.
似乎没有 Reset 方法
var count = await itemsToImport.CountAsync();
await foreach (var importEntity in itemsToImport)
{
// won't run
}
数据来源:
private IAsyncEnumerable<TEntity> InternalImportFromStream(TextReader reader)
{
var csvReader = new CsvReader(reader, Config);
return csvReader.GetRecordsAsync<TEntity>();
}
似乎无法通过接口本身重置 IAsyncEnumerable,因为 IAsyncEnumerator 接口上没有 Reset 方法。
在这个具体示例中,第二个枚举将不起作用,因为 IAsyncEnumerable 以 Stream 为目标。读取流后,位置光标将指向流的末尾。如果您可以控制流或对它的引用(我没有),您可以再次将位置设置为 0 并再次枚举它。
我倾向于使用 ToListAsync,然后从其计数中获取计数 属性 并同步迭代项目,因为它们已经加载。
这与重置 IAsyncEnumerator 无关。此代码尝试生成第二个 IAsyncEnumerator,这与 IEnumerable.GetEnumerator() 一样仅适用于某些类型的集合。如果 Enumerable(异步或非异步)是对某种只进数据结构的抽象,那么 GetEnumerator/GetAsyncEnumerator 将失败。
即使它没有失败,有时也很昂贵。例如,每次枚举时它可能 运行 一个数据库查询或命中一个远程 API。这就是为什么 IEnumerable/IAsyncEnumerable 从函数中生成糟糕的 public return 类型,因为它们无法描述 returned 集合的功能,而且几乎是你唯一可以用该值是用 .ToList/ToListAsync.
实现的
例如,这很好用:
static async IAsyncEnumerable<int> Col()
{
for (int i = 1; i <= 10; i++)
{
yield return i;
}
}
static void Main(string[] args)
{
Run().Wait();
}
static async Task Run()
{
var col = Col();
var count = await col.CountAsync();
await foreach (var dataPoint in col)
{
Console.WriteLine(dataPoint);
}
}
运行 枚举 IAsyncEnumerable
两次不可能?
一旦 CountAsync
变为 运行,await foreach
将不会枚举任何项目。为什么?
AsyncEnumerator
.
var count = await itemsToImport.CountAsync();
await foreach (var importEntity in itemsToImport)
{
// won't run
}
数据来源:
private IAsyncEnumerable<TEntity> InternalImportFromStream(TextReader reader)
{
var csvReader = new CsvReader(reader, Config);
return csvReader.GetRecordsAsync<TEntity>();
}
似乎无法通过接口本身重置 IAsyncEnumerable,因为 IAsyncEnumerator 接口上没有 Reset 方法。
在这个具体示例中,第二个枚举将不起作用,因为 IAsyncEnumerable 以 Stream 为目标。读取流后,位置光标将指向流的末尾。如果您可以控制流或对它的引用(我没有),您可以再次将位置设置为 0 并再次枚举它。
我倾向于使用 ToListAsync,然后从其计数中获取计数 属性 并同步迭代项目,因为它们已经加载。
这与重置 IAsyncEnumerator 无关。此代码尝试生成第二个 IAsyncEnumerator,这与 IEnumerable.GetEnumerator() 一样仅适用于某些类型的集合。如果 Enumerable(异步或非异步)是对某种只进数据结构的抽象,那么 GetEnumerator/GetAsyncEnumerator 将失败。
即使它没有失败,有时也很昂贵。例如,每次枚举时它可能 运行 一个数据库查询或命中一个远程 API。这就是为什么 IEnumerable/IAsyncEnumerable 从函数中生成糟糕的 public return 类型,因为它们无法描述 returned 集合的功能,而且几乎是你唯一可以用该值是用 .ToList/ToListAsync.
实现的例如,这很好用:
static async IAsyncEnumerable<int> Col()
{
for (int i = 1; i <= 10; i++)
{
yield return i;
}
}
static void Main(string[] args)
{
Run().Wait();
}
static async Task Run()
{
var col = Col();
var count = await col.CountAsync();
await foreach (var dataPoint in col)
{
Console.WriteLine(dataPoint);
}
}