File.ReadLine打开的文件是否因异常而关闭?

时间:2015-01-22 11:14:20

标签: c# .net io

如果在迭代生成的可枚举数据时抛出异常,则通过File.ReadLines读取的文件是否已关闭?

示例:

File.ReadLines("file.txt")
    .Select(line => { throw new Exception(); return 1; });

file.txt是否一直关闭?

如果它确实关闭了,那么迭代将不会继续的事实如何由实现决定呢?

我无法理解文件如何关闭的原因如下。我怀疑ReadLines实现是这样的:

IEnumerable<string> ReadLines(string file)
{
    using (var reader <Open reader>)
    {
        String line = null;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    } 
}

如果在迭代期间抛出异常,则不会从生成的枚举器中提取所有行。然后在永远不会到达while - 语句后行,using - 语句将无法关闭流。

2 个答案:

答案 0 :(得分:3)

当使用foreach的枚举中止时,将调度枚举器。在这种“早期部署”的情况下,C#迭代器方法执行所有活动的finally块。这意味着迭代器方法中的所有using语句都得到尊重,因为using基于finally

为了使其更具体:Dispose只能在yield return语句的C#生成的枚举器上调用。只有yield return放弃了对来电者的控制权。

生成的状态机会跟踪每个屈服点上最终块的活动状态,并使用Dispose方法执行它们。

如果你只是放弃一个枚举器(File.ReadLines("file.txt").GetEnumerator();),那么最后的块就不会被尊重了。没有机制可以做到这一点。

TL; DR:只要您处置最外层的枚举器并且链中的所有枚举器(此处:SelectReadLines)正确使用其内部枚举器进行处置,文件就会在所有情况下都被关闭finally

答案 1 :(得分:1)

是的,它将被关闭。它在FileStream内部创建StreamReader,并在using块中使用它。 我不确定你在第二个问题中的意思(你可以简单地抓住例外)。