.net framework 4.0的File.ReadLines(..)方法中的错误

Adr*_*tin 11 .net c# c#-4.0

这段代码:

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查询的结果之前,您还必须调用该方法.

ric*_*ard 6

我知道这是旧的,但我实际上只是在Windows 7机器上处理一些代码时遇到了这个问题.与人们在这里所说的相反,这实际上一个错误.看到这个链接.

所以简单的解决方法是更新您的.net framefork.我认为这值得更新,因为这是最热门的搜索结果.


jmo*_*eno 5

我不认为这是一个错误,我不认为这是不寻常的 - 事实上,这是我期望的文本文件阅读器之类的东西.IO是一项昂贵的操作,因此通常您希望一次性完成所有操作.

  • 是的,但读者可以在IEnumerable.GetEnumerator调用中创建,即枚举开始时,而不是创建IEnumerable时.我同意Adrian,这将是更可预测的行为,并且更容易与新方法旨在支持的LINQ运算符一起使用(并且由于它们是懒惰的,因此与那些LINQ运算符更加一致). (8认同)