Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need to consider disposing of any IEnumerable<T> I use?

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?

like image 767
Rob Avatar asked Nov 19 '12 17:11

Rob


People also ask

What is IEnumerable t in c#?

IEnumerable. IEnumerable<T> contains a single method that you must implement when implementing this interface; GetEnumerator, which returns an IEnumerator<T> object. The returned IEnumerator<T> provides the ability to iterate through the collection by exposing a Current property.

Why to dispose objects in c# net?

The dispose pattern is used for objects that implement the IDisposable interface, and is common when interacting with file and pipe handles, registry handles, wait handles, or pointers to blocks of unmanaged memory. This is because the garbage collector is unable to reclaim unmanaged objects.

What is IEnumerable?

IEnumerable is an interface defining a single method GetEnumerator() that returns an IEnumerator interface. It is the base interface for all non-generic collections that can be enumerated. This works for read-only access to a collection that implements that IEnumerable can be used with a foreach statement.

How to use IEnumerable in vb net?

You can create a class that implements the IEnumerable<T> interface to expose source data as enumerable data. Your class that implements the IEnumerable(T) interface will require another class that implements the IEnumerator<T> interface to iterate through the source data.


1 Answers

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.)

like image 72
Jon Skeet Avatar answered Sep 27 '22 20:09

Jon Skeet