在C#中如何封装抽取包含yield return的重复IAsyncEnumerable代码块?
解决方案
你可以通过编写泛型的异步迭代器公共方法,配合await foreach遍历产出元素实现重复逻辑抽离,也可以封装成扩展方法进一步简化调用。
步骤1:编写公共泛型迭代方法
你可以直接封装成通用扩展方法,适配所有IAsyncCursor<T>类型的游标遍历场景:
public static class AsyncCursorExtensions { /// <summary> /// 将MongoDB异步游标转换为IAsyncEnumerable<T>序列 /// </summary> public static async IAsyncEnumerable<T> ToAsyncEnumerable<T>(this IAsyncCursor<T> cursor) { ArgumentNullException.ThrowIfNull(cursor); while (await cursor.MoveNextAsync()) { foreach (T item in cursor.Current) { yield return item; } } } }
步骤2:重构业务方法
在原有业务方法中拿到游标后,遍历公共方法返回的异步序列逐个产出即可,完全保留原有方法的签名和行为:
public async IAsyncEnumerable<FieldServiceAppointment> GetEventWithWorkOrderType( string workOrderType, string customerId) { using IAsyncCursor<FieldServiceAppointment> cursor = await FieldServiceAppointments.FindAsync( x => x.BusinessEventTypeCode == workOrderType && x.CustomerCode == customerId ); // 仅需一行代码替换原有重复的双层循环 await foreach (var appointment in cursor.ToAsyncEnumerable()) { yield return appointment; } }
该写法完全安全,using块会在异步迭代器执行完毕后自动释放游标,不会出现资源泄漏问题。
之前报错的原因说明
- 直接调用公共方法不做返回/产出:
async IAsyncEnumerable<T>属于异步迭代器方法,方法体内必须包含至少一个yield return语句才符合语法规范,无产出逻辑就会触发「无法从迭代器返回值」错误 - 用
yield return YieldAppointments():yield return每次只能产出单个T类型的元素,你返回的是整个IAsyncEnumerable<T>序列,类型不匹配因此报CS0266错误 - 返回值改为
Task<FieldServiceAppointment>:异步迭代器的合法返回值只能是IAsyncEnumerable<T>或IAsyncEnumerator<T>,返回Task不符合要求因此报CS1624错误
内容的提问来源于stack exchange,提问作者Brian Kessler
相关产品推荐
相关产品推荐

