【发布时间】:2011-04-13 02:54:40
【问题描述】:
有很多 Linq 算法只需要对输入进行一次传递,例如选择。
然而,所有的 Linq 扩展方法都位于 IEnumerable 而不是 IEnumerator
var e = new[] { 1, 2, 3, 4, 5 }.GetEnumerator();
e.Select(x => x * x); // Doesn't work
这意味着您不能在任何从“已经打开”的流中读取的情况下使用 Linq。
这种情况在我目前正在处理的项目中经常发生 - 我想返回一个 IEnumerator,其 IDispose 方法将关闭流,并让所有下游 Linq 代码对此进行操作。
简而言之,我有一个“已经打开”的结果流,我可以将其转换为适当的一次性 IEnumerator - 但不幸的是,所有下游代码都需要一个 IEnumerable 而不是 IEnumerator,即使它只会做一个“通过”。
即我想在各种不同的源(CSV 文件、IDataReaders 等)上“实现”这种返回类型:
class TabularStream
{
Column[] Columns;
IEnumerator<object[]> RowStream;
}
为了获得“列”,我必须已经打开了 CSV 文件,启动了 SQL 查询,或者其他。然后我可以返回一个“IEnumerator”,其 Dispose 方法会关闭资源 - 但所有 Linq 操作都需要一个 IEnumerable。
我所知道的最好的解决方法是实现一个 IEnumerable,它的 GetEnumerator() 方法返回唯一的 IEnumerator,如果尝试调用 GetEnumerator() 两次,则会引发错误。
这一切听起来都不错,还是有更好的方法让我以易于从 Linq 使用的方式实现“TabularStream”?
【问题讨论】: