是否不可能两次运行IAsyncEnumerable的枚举



是否不可能对IAsyncEnumerable执行两次枚举?

一旦运行了CountAsyncawait 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>();
}

这与重置IAsyncEnumerator无关。这段代码试图生成第二个IAsyncEnumerator,就像IEnumerable一样。GetEnumerator((只能用于某些类型的集合。如果Enumerable(异步或非异步(是对某种仅前向数据结构的抽象,那么GetEnumerator/GetAsyncEnumerator将失败。

即使它没有失败,有时也很昂贵。例如,它可能会运行数据库查询,或者每次枚举时都会调用远程API。这就是为什么IEnumerable/IAsyncEnumerable从函数中生成糟糕的公共返回类型的原因,因为它们无法描述返回集合的功能,而且对该值几乎唯一能做的就是用实现它。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);
}
}

由于IAsyncEnumerator接口上没有reset方法,因此似乎不可能通过接口本身重置IAsyncEn枚举。

在这个特定的示例中,第二个枚举将不起作用,因为IAsyncEnumerable的目标是Stream。一旦读取了流,位置光标就会指向流的末尾。如果你可以控制流或引用它(我没有(,你可以再次将位置设置为0并再次枚举它。

我倾向于使用ToListAsync,然后从其count属性中获取count,并同步迭代项,因为它们已经加载。

最新更新