我是否需要考虑处理我使用的任何 IEnumable < T > ?

最近有人向我指出,各种 Linq 扩展方法(如 WhereSelect等)返回的 IEnumerable<T>恰好也是 IDisposable。下面的计算结果为 True

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

是否需要处理 Where表达式的结果?

每当我调用返回 IEnumerable<T>的方法时,我是否(可能)在完成处理后接受调用释放的责任?

20860 次浏览

不,你不用担心这个。

它们返回一个 IDisposable实现的事实是一个实现细节——这是因为 C # 编译器的 Microsoft 实现中的迭代器块碰巧创建了一个同时实现 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。因此,无论何时显式迭代,都应该正确地处理它。例如,如果希望对某些内容进行迭代,并确保始终具有 值,那么可以使用以下内容:

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循环将自动执行此操作。)