77

最近有人向我指出,各种 Linq 扩展方法(例如Where,Select等)返回的 anIEnumerable<T>也恰好是IDisposable. 以下评估为True

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

我需要处理Where表达式的结果吗?

每当我调用一个方法时IEnumerable<T>,我是否(可能)在我完成后接受调用 dispose 的责任?

4

1 回答 1

91

不,你不需要担心这个。

他们返回一个实现的事实IDisposable是一个实现细节 - 这是因为 C# 编译器的 Microsoft 实现中的迭代器块碰巧创建了一个实现和的单一类型。后者 extends ,这就是你看到它的原因。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当然,循环会自动执行此操作。)

于 2012-11-19T18:02:27.153 回答