如果在迭代生成的可枚举数据时抛出异常,则通过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
- 语句将无法关闭流。
答案 0 :(得分:3)
当使用foreach
的枚举中止时,将调度枚举器。在这种“早期部署”的情况下,C#迭代器方法执行所有活动的finally块。这意味着迭代器方法中的所有using
语句都得到尊重,因为using
基于finally
。
为了使其更具体:Dispose
只能在yield return
语句的C#生成的枚举器上调用。只有yield return
放弃了对来电者的控制权。
生成的状态机会跟踪每个屈服点上最终块的活动状态,并使用Dispose
方法执行它们。
如果你只是放弃一个枚举器(File.ReadLines("file.txt").GetEnumerator();
),那么最后的块就不会被尊重了。没有机制可以做到这一点。
TL; DR:只要您处置最外层的枚举器并且链中的所有枚举器(此处:Select
和ReadLines
)正确使用其内部枚举器进行处置,文件就会在所有情况下都被关闭finally
。
答案 1 :(得分:1)
是的,它将被关闭。它在FileStream内部创建StreamReader,并在using块中使用它。 我不确定你在第二个问题中的意思(你可以简单地抓住例外)。