代码之家  ›  专栏  ›  技术社区  ›  David

File.ReadLines何时释放资源

  •  12
  • David  · 技术社区  · 14 年前

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

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

    显然,由于这个方法返回的是IEnumerable、not和IDisposable,所以我无法接受对using语句的本能反应。

    我的问题是:

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

    2 回复  |  直到 14 年前
        1
  •  19
  •   Lasse V. Karlsen    14 年前

    IEnumerable 不从IDisposable继承,因为实现它的类通常只提供 承诺 由于是可枚举的,它实际上还没有做任何值得处理的事情。

    但是,当您在上面枚举时,首先检索 IEnumerator 打电话给 IEnumerable.GetEnumerator 方法,通常是返回的底层对象 实施 IDisposable

    顺便说一句 foreach 实现方式与此类似:

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

    这样,如果对象确实实现了 可识别的 File.ReadLines ,在开始枚举之前,文件不会真正打开,因此 不需要处理,但你得到的枚举数需要。

    正如评论所指出的, 迭代器 不继承自 可识别的 IEnumerator<T> 是否继承 可识别的 .

        2
  •  5
  •   Matthew Abbott    14 年前

    +拉丝的答案是1。

    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;
    }
    
        3
  •  0
  •   Erdogan Kurtur    3 年前

    只是为了更新:

    在.net 5中 IEnumerable IDisposable 你可能需要打电话 Dispose