我正在编写如下程序:
- 在给定目录中查找所有具有正确扩展名的文件
- Foreach,在这些文件中查找给定字符串的所有出现
- 打印每一行
我想以一种功能性的方式编写它,作为一系列生成器函数(调用yield return
并且一次只返回一个项目的东西延迟加载),所以我的代码将如下所示:
IEnumerable<string> allFiles = GetAllFiles();
IEnumerable<string> matchingFiles = GetMatches( "*.txt", allFiles );
IEnumerable<string> contents = GetFileContents( matchingFiles );
IEnumerable<string> matchingLines = GetMatchingLines( contents );
foreach( var lineText in matchingLines )
Console.WriteLine( "Found: " + lineText );
这一切都很好,但我还想做的是在最后打印一些统计数据。像这样的东西:
Found 233 matches in 150 matching files. Scanned 3,297 total files in 5.72s
问题是,像上面那样以“纯功能”风格编写代码,每个项目都是延迟加载的。
在最终的 foreach 循环完成之前,您只知道总共有多少文件匹配,并且因为一次只yield
编辑一个项目,所以代码没有任何地方可以跟踪它之前找到了多少东西。如果您调用 LINQ 的matchingLines.Count()
方法,它将重新枚举集合!
我可以想出很多方法来解决这个问题,但它们似乎都有些难看。它让我印象深刻,因为人们以前一定会做过,而且我相信会有一个很好的设计模式来展示做这件事的最佳实践方式。
有任何想法吗?干杯