这段代码:
IEnumerable<string> lines = File.ReadLines("file path");
foreach (var line in lines)
{
Console.WriteLine(line);
}
foreach (var line in lines)
{
Console.WriteLine(line);
}
Run Code Online (Sandbox Code Playgroud)
ObjectDisposedException : {"Cannot read from a closed TextReader."}如果第二个foreach执行则抛出一个.似乎返回的迭代器对象File.ReadLines(..)不能多次枚举.您必须通过调用获取新的迭代器对象File.ReadLines(..),然后使用它进行迭代.
如果我File.ReadLines(..)用我的版本替换(参数未经验证,那只是一个例子):
public static IEnumerable<string> MyReadLines(string path)
{
using (var stream = new TextReader(path))
{
string line;
while ((line = stream.ReadLine()) != null)
{
yield return line;
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以多次迭代文件的行.
使用调查.Net Reflector表明,File.ReadLines(..)调用private的File.InternalReadLines(TextReader reader)实现创建了实际的迭代器.作为参数传递的读者MoveNext()在迭代器的方法中用于获取文件的行,并在到达文件末尾时被释放.这意味着一旦MoveNext()返回false,就无法再次迭代,因为读取器已关闭,您必须通过使用该ReadLines(..)方法创建新的迭代器来获取新的读取器.在我的版本中,MoveNext()每次在该方法中创建一个新的读取器我们开始一个新的迭代.
这是File.ReadLines(..)方法的预期行为吗?
我发现令人不安的事实是,每次枚举结果之前都必须调用该方法.每次迭代使用该方法的Linq查询的结果之前,您还必须调用该方法.
我不认为这是一个错误,我不认为这是不寻常的 - 事实上,这是我期望的文本文件阅读器之类的东西.IO是一项昂贵的操作,因此通常您希望一次性完成所有操作.