File.ReadLine 打开的文件是否在异常时关闭?

Are files opened by File.ReadLine closed on exceptions?

如果在遍历生成的可枚举对象时抛出异常,通过 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-statement 之后的行永远不会到达并且 using-statement 将没有机会关闭流。

是的,它将被关闭。它在内部通过 FileStream 创建一个 StreamReader 并在 using 块中使用它。 我不确定你在第二个问题中的意思(你可以简单地捕获异常)。

当使用 foreach 的枚举被中止时,枚举器将被丢弃。在 "early dispose" 的情况下,C# 迭代器方法执行所有活动的 finally 块。这意味着迭代器方法内的所有 using 语句都被接受,因为 using 基于 finally.

为了使其更具体:Dispose 只能在 yield return 语句中的 C# 生成的枚举器上调用。只有 yield return 将控制权交给调用者。

生成的状态机跟踪在每个屈服点激活的 finally 块,并在 Dispose 方法中执行它们。

如果您简单地放弃一个枚举器 (File.ReadLines("file.txt").GetEnumerator();),finally 块将不会被接受。没有机制可以做到这一点。

TL;DR:只要您处置最外层的枚举器和链中​​的所有枚举器(此处:SelectReadLines)正确处置它们的内部,文件在所有情况下都会被关闭使用 finally.

的枚举器