1. ホーム
  2. c#

使用したIEnumerable<T>の廃棄を考慮する必要がありますか?

2023-10-10 19:22:42

質問

最近指摘されたのですが、様々なLinq拡張メソッド(例えば Where , Select など) は IEnumerable<T> であり、かつ IDisposable . 次のように評価されます。 True

new int[2] {0,1}.Select(x => x*2) is IDisposable

の結果を廃棄する必要があるのでしょうか? Where 式の結果を処分する必要がありますか?

を返すメソッドを呼び出すと、必ず IEnumerable<T> を返すメソッドを呼び出すたびに、それを使い終わったときに dispose を呼び出す責任を(潜在的に)引き受けることになるのでしょうか?

どのように解決するのですか?

いいえ、ご心配には及びません。

を返すということは IDisposable Microsoft の C# コンパイラの実装では、イテレータブロックがたまたま シングル 型の両方を実装しているためです。 IEnumerable<T>IEnumerator<T> . 後者は IDisposable を拡張しているため、このように表示されます。

デモのためのサンプルコードです。

using System;
using System.Collections.Generic;

public class Test 
{
    static void Main() 
    {
        IEnumerable<int> foo = Foo();
        Console.WriteLine(foo is IDisposable); // Prints True
    }

    static IEnumerable<int> Foo()
    {
        yield break;
    }
}

注意点として する が必要であることに注意してください。 IEnumerator<T> が実装している IDisposable . ですから、明示的に反復処理するときはいつでも、適切に廃棄する必要があります。例えば、何かに対して反復処理を行いたい場合、常に a の値を持つようにしたい場合、次のようなものを使うかもしれません。

using (var enumerator = enumerable.GetEnumerator())
{
    if (!enumerator.MoveNext())
    {
        throw // some kind of exception;
    }
    var value = enumerator.Current;
    while (enumerator.MoveNext())
    {
        // Do something with value and enumerator.Current
    }
}

(A foreach ループはもちろんこれを自動的に行います)。