如何在F#异步表达式中使用while循环?优化C#异步读取的F#实现
异步数据库读取的C#到F#改写优化方案
原始C#代码
var reader = await someDatabaseCommand.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var foo = reader.GetDouble(1); // ... 业务逻辑代码 }
新手尝试的F#代码
task { let! reader = someDatabaseCommand.ExecuteReaderAsync () let! tmp1 = reader.ReadAsync () let mutable hasNext = tmp1 while hasNext do // ... 业务逻辑代码 let! tmp2 = reader.ReadAsync () hasNext <- tmp2 }
递归实现方案(无临时变量)
如果想避免可变变量和临时变量,用递归是F#里更符合函数式风格的方案,代码如下:
task { let! reader = someDatabaseCommand.ExecuteReaderAsync() // 定义尾递归函数处理逐行读取 let rec readNext () = task { let! hasNext = reader.ReadAsync() if hasNext then // 处理当前行数据,示例获取第2列的double值(索引从0开始,这里1对应第二列) let foo = reader.GetDouble(1) // ... 这里写你的业务逻辑 // 递归处理下一行 return! readNext() else // 无更多数据,结束流程 return () } // 启动递归读取流程 return! readNext() }
说明
- 这个方案完全去掉了可变变量和临时变量,用尾递归替代了while循环
- F#会对尾递归进行优化,不会出现栈溢出问题
- 逻辑和原始C#代码完全一致:先获取reader,然后逐行读取直到没有更多数据
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

