【发布时间】:2015-01-22 11:14:20
【问题描述】:
如果在迭代生成的可枚举时引发异常,是否会关闭通过 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 将没有机会关闭流。
【问题讨论】:
-
为什么不关闭文件? using 语句使用 finally,因此无论异常如何都会被处理
-
但是while循环只有在所有行都被读取后才会终止。除非客户端使用生成的枚举器实际完成迭代,否则情况并非如此。如果在迭代期间抛出异常,则枚举器不会获取某些元素,并且 while 循环不应终止。
-
你需要查看
Select的实现,看看它为什么会被关闭。 -
@JamesBarrass 1) 这是一个迭代器,所以
finally语句与普通的finally语句完全不同。 finally 语句在迭代器到达末尾(对于 OP 永远不会发生)或迭代器被释放时执行。如果处置没有发生,则关闭文件将延迟到迭代器的终结器,如果有的话,它可能会运行得更晚。 2) always 很强大,有一堆情况,其中大多数涉及强制进程终止而不执行。 -
@CodesInChaos,是的,在某些情况下 finally 语句没有被执行,但我认为它们与问题无关,可能不应该让它变得粗体。 1) 我很感兴趣,所以我来调查一下!