File.ReadLines何时释放资源
在使用C#中的文件时,我习惯于考虑释放相关资源。 通常这是一个using语句,除非它是像File.ReadAllLines这样的单行内容方法,它将为我打开和关闭文件。
.Net 4.0引入了方便的File.ReadLines方法。 这将返回一个IEnumerable,并被视为一种更有效的方式来处理文件 – 它避免将整个文件存储在内存中。 为此,我假设枚举器中有一些延迟执行逻辑。
显然,因为这个方法返回一个IEnumerable,而不是IDisposable,我不能用我对使用语句的直觉反应。
我的问题是:考虑到这一点,使用此方法是否存在资源释放的问题?
调用此方法是否意味着关联文件锁的释放是不确定的?
IEnumerable
不会从IDisposableinheritance,因为通常,实现它的类只能为您提供可枚举的承诺 ,它实际上还没有做任何可以处理的事情。
但是,当您枚举它时,首先通过调用IEnumerable.GetEnumerator
方法来检索IEnumerable.GetEnumerator
,通常,您获取的基础对象确实实现了IDisposable
。
foreach
的实现方式与此类似:
var enumerator = enumerable.GetEnumerator(); try { // enumerate } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) disposable.Dispose(); }
这样,如果对象确实实现了IDisposable
,它将被处理掉。 对于File.ReadLines
,在你开始枚举文件之前,文件并没有真正打开,所以你从File.ReadLines
获得的对象不需要处理,但你得到的枚举器就是这样。
正如注释所示, IEnumerator
并不inheritance自IDisposable
,即使许多典型的实现都是如此,而通用的IEnumerator
确实inheritance了IDisposable
。
Lasse的回答是+1。
特别是对于枚举器调用.MoveNext()
的File.ReadLines
,当遇到EOF或发生故障时,内部TextReader
将被丢弃。
private bool MoveNext() { bool flag; try { switch (this.<>1__state) { case 0: this.<>1__state = -1; this.<>7__wrap2 = this.reader; this.<>1__state = 1; this.5__1 = null; goto Label_005C; case 2: this.<>1__state = 1; goto Label_005C; default: goto Label_0078; } Label_003E: this.<>2__current = this. 5__1; this.<>1__state = 2; return true; Label_005C: if ((this. 5__1 = this.reader.ReadLine()) != null) { goto Label_003E; } this.<>m__Finally3(); // Disposal at end of file. Label_0078: flag = false; } fault { this.System.IDisposable.Dispose(); // Disposal due to fault. } return flag; }