It's recently been pointed out to me that various Linq extension methods (such as Where, Select, etc) return an IEnumerable<T> that also happens to be IDisposable. The following evaluates to True
new int[2] {0,1}.Select(x => x*2) is IDisposable
Do I need to dispose of the results of a Where expression?
Whenever I call a method returning IEnumerable<T>, am I (potentially) accepting responsibility for calling dispose when I've finished with it?
No, you don't need to worry about this.
The fact that they return an IDisposable implementation is an implementation detail - it's because iterator blocks in the Microsoft implementation of the C# compiler happen to create a single type which implements both IEnumerable<T> and IEnumerator<T>. The latter extends IDisposable, which is why you're seeing it.
Sample code to demonstrate this:
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;
}
}
Note that you do need to take note of the fact that IEnumerator<T> implements IDisposable. So any time you iterate explicitly, you should dispose of it properly. For example, if you want to iterate over something and be sure that you'll always have a value, you might use something like:
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 loop will do this automatically, of course.)
来源:https://stackoverflow.com/questions/13459447/do-i-need-to-consider-disposing-of-any-ienumerablet-i-use