最近、さまざまなLinq拡張メソッド(Where
、Select
など)がIEnumerable<T>
を返すことが指摘されましたが、これはたまたまIDisposable
でもあります。以下はTrue
に評価されます
new int[2] {0,1}.Select(x => x*2) is IDisposable
Where
式の結果を破棄する必要がありますか?
IEnumerable<T>
を返すメソッドを呼び出すたびに、処理を終えたときにdisposeを呼び出す責任を(潜在的に)受け入れますか?
いいえ、これについて心配する必要はありません。
それらがIDisposable
実装を返すという事実は実装の詳細です。C#コンパイラのMicrosoft実装のイテレータブロックは、IEnumerable<T>
とIEnumerator<T>
の両方を実装するsingleタイプを作成するためです。後者は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;
}
}
doは、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
}
}
(もちろん、foreach
ループがこれを自動的に行います。)