最近有人向我指出,各种Linq扩展方法(例如Where
,Select
等)返回的IEnumerable<T>
也恰好是IDisposable
。以下评估结果为True
new int[2] {0,1}.Select(x => x*2) is IDisposable
我是否需要处理Where
表达式的结果?
每当我调用一个返回IEnumerable<T>
的方法时,我(可能)接受了在我完成后调用dispose的责任吗?
答案 0 :(得分:81)
不,你不必担心这个。
它们返回IDisposable
实现的事实是一个实现细节 - 这是因为C#编译器的Microsoft实现中的迭代器块碰巧创建了一个单类型,它实现了两个{{ 1}}和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
}
}
循环会自动执行此操作。)