File.ReadLines何时释放资源

Dav*_*vid 13 c# .net-4.0

在使用C#中的文件时,我习惯于考虑释放相关资源.通常这是一个using语句,除非它是像File.ReadAllLines这样的单行内容方法,它将为我打开和关闭文件.

.Net 4.0引入了方便的File.ReadLines方法.这将返回一个IEnumerable,并被视为一种更有效的方法来处理文件 - 它避免将整个文件存储在内存中.为此,我假设枚举器中有一些延迟执行逻辑.

显然,因为这个方法返回一个IEnumerable,而不是IDisposable,我不能用我对使用语句的直觉反应.

我的问题是:考虑到这一点,使用此方法是否存在资源释放的问题?

调用此方法是否意味着关联文件锁的释放是不确定的?

ang*_*son 17

IEnumerable不会从IDisposable继承,因为通常,实现它的类只会给你可枚举的承诺,它实际上没有做任何可以处理的事情.

但是,当您枚举它时,首先IEnumerator通过调用IEnumerable.GetEnumerator方法来检索,通常,您获取的基础对象确实实现了IDisposable.

的方式foreach实现与此类似:

var enumerator = enumerable.GetEnumerator();
try
{
    // enumerate
}
finally
{
    IDisposable disposable = enumerator as IDisposable;
    if (disposable != null)
        disposable.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

这样,如果对象确实实现了IDisposable,它将被处理掉.因为File.ReadLines,在你开始枚举文件之前,文件并没有真正打开,所以你得到的对象File.ReadLines不需要处理,但是你得到的枚举器就是这样.

正如评论所指出的IEnumerator那样IDisposable,即使许多典型的实现都没有继承,但泛型IEnumerator<T>确实继承了IDisposable.

  • 更正:非通用IEnumerator不实现IDisposable,但通用的(IEnumerator <T>`)实现. (3认同)

Mat*_*ott 5

+1为Lasse的答案。

特别是对于File.ReadLines枚举器调用.MoveNext()的地方TextReader,当遇到EOF或发生故障时,将处理内部。

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.<line>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.<line>5__1;
        this.<>1__state = 2;
        return true;
    Label_005C:
        if ((this.<line>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;
}
Run Code Online (Sandbox Code Playgroud)