File.ReadLines何时释放资源

时间:2010-07-31 18:08:27

标签: c# .net-4.0

使用C#中的文件时,我习惯于考虑释放相关资源。通常这是一个使用声明,除非它是一个简单的方法 就像File.ReadAllLines一样,它会为我打开和关闭文件。

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

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

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

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

3 个答案:

答案 0 :(得分:17)

IEnumerable不会从IDisposable继承,因为通常,实现它的类只会为您提供可枚举的 promise ,它实际上还没有做任何可以处理的事情。

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

实施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,即使有许多典型的实现,但通用IDisposable确实会继承IEnumerator<T>

答案 1 :(得分: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;
}

答案 2 :(得分:0)

只是为了更新:

在 .net 5 中,它返回的 IEnumerable 确实实现了 IDisposable,您可能需要在转换后调用 Dispose。但是如果你读到文件末尾,它会自行处理。