我试图获取服务器中所有数据库的列表,并最终打印出来(即将其名称用作string
s)。使用以前版本的c#驱动程序,我可以调用Server.GetDatabases()
,但已将其替换为ListDatabasesAsync()
。
返回值为IAsyncCursor<>
,我不知道如何处理它。如何用这样的光标遍历数据库列表(或任何东西)?
答案 0 :(得分:27)
简答:使用ForEachAsync
扩展方法:
var cursor = await client.ListDatabasesAsync();
await cursor.ForEachAsync(db => Console.WriteLine(db["name"]));
答案很长:C#中的传统迭代是使用IEnumerable
和foreach
完成的。 foreach
是编译器的语法糖。它实际上是对GetEnumerator
,using
范围和while
循环的调用。但这并不支持异步操作:
using (var enumerator = enumerable.GetEnumerator())
{
while (enumerator.MoveNext())
{
var current = enumerator.Current;
// use current.
}
}
IAsyncCursor
相当于IEnumerator
(IEnumerable.GetEnumerator
的结果)而IAsyncCursorSource
相当于IEnumerable
。不同之处在于这些支持async
(并且每次迭代都获得批处理,而不仅仅是单个项目)。您不能使用为foreach
构建的IEnumerable
,但您可以实现整个using
,while
循环内容:
IAsyncCursorSource<int> cursorSource = null;
using (var asyncCursor = await cursorSource.ToCursorAsync())
{
while (await asyncCursor.MoveNextAsync())
{
foreach (var current in asyncCursor.Current)
{
// use current
}
}
}
然而,这是很多样板,因此驱动程序为IAsyncCursor
,ForEachAsync
等ToListAsync
添加了扩展方法。
这涵盖了大多数常见用例,但对于其他用户,您仍需要自己实现迭代。
答案 1 :(得分:3)
我个人很喜欢将光标转换为C#8 IAsyncEnumerable
,这样您就可以获得使用枚举(主要是LINQ
)的所有好处。
使用@ i3arnon的“长答案”,我创建了此扩展方法:
public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncCursor<T> asyncCursor)
{
while (await asyncCursor.MoveNextAsync())
{
foreach (var current in asyncCursor.Current)
{
yield return current;
}
}
}