Why does IEnumerator <T> inherit from IDisposable and not the generic IEnumerator - no?

I noticed that the generic IEnumerator<T> inherits from IDisposable, but not the generic IEnumerator interface does. Why is it designed this way?

Usually we use the foreach statement to traverse an instance of IEnumerator<T> . The generated foreach code actually has a try-finally block that ultimately calls Dispose ().

+59
generics c # ienumerator
Oct 24 '08 at 5:27
source share
6 answers

It was mostly an oversight. In C # 1.0, foreach never called Dispose 1 . With C # 1.2 (introduced in VS2003 - there is 1.1 there, it is strange) foreach began to check the finally block to see if the IDisposable iterator was implemented - they should have done it this way because, in retrospect, creating an IEnumerator the IDisposable extension would break all IEnumerator implementations. If they assumed that it was useful for foreach dispose of iterators in the first place, I am sure that IEnumerator would extend IDisposable .

When C # 2.0 and .NET 2.0 appeared, they had a new opportunity - a new interface, a new inheritance. It makes much more sense to extend the IDisposable interface, so you don't need to check the runtime in the finally block, and now the compiler knows that if the iterator is IEnumerator<T> , it can emit an unconditional call to Dispose .

EDIT: It is incredibly useful for Dispose to be called at the end of the iteration (however it ends). This means that an iterator can grab onto resources, which makes it possible, say, to read a file line by line. The iterator blocks the Dispose generator, which ensures that any finally blocks related to the "current execution point" of the iterator are executed when it is placed, so you can write normal code in the iterator, and cleanup should happen accordingly.




1 Looking back at specification 1.0, it has already been specified. I have not been able to verify this previous statement that implementation 1.0 did not call Dispose .

+66
Oct 24 '08 at 6:06
source share

IEnumerable <T> does not inherit IDisposable. However, IEnumerator <T> inherits IDisposable, while non-trivial IEnumerator does not. Even if you use foreach for non-generic IEnumerable (which returns an IEnumerator), the compiler will still generate an IDisposable check and call Dispose () if the enumerator implements the interface.

I assume that the generic Enumerator <T> inherits from IDisposable, so there is no need to do a runtime type check, it can just go and call Dispose (), which should have better performance, since it can probably be optimized if the enumerator is empty Dispose () method.

+4
Oct 24 '08 at 5:56
source share

I know this is an old discussion, but I intelligently wrote a library where I used IEnumerable from T / IEnumerator of T, where library users could implement custom iterators, they should just implement IEnumerator from T.

It was very strange to me that IEnumerator of T inherits from IDisposable. Are we implementing IDisposable if we want to free up unused resources? Thus, for counters, it would really be true to have unmanaged resources - for example, an I / O stream, etc. Why not just let users implement IEnumerator from T and IDisposable in their enumerator, if that makes sense? In my book, this violates the principle of a single responsibility - why mix the logic of the enumerator and dispose of objects.

+3
Dec 28
source share

Is IEnumerable `inherit IDisposing? According to the .NET or MSDN reflector. Are you sure you are not mixing it with IEnumerator ? This uses IDisposing because it is intended only for listing the collection and is not intended for durability.

0
Oct 24 '08 at 5:45
source share

It is a little difficult to be final on this unless you manage to get an answer from AndersH himself or someone near him.

However, I assume that it refers to the yield keyword, which was introduced simultaneously in C #. If you look at the code generated by the compiler when "yield return x" is used, you will see a method terminated in a helper class that implements IEnumerator; descent of IEnumerator from IDisposable ensures that it can clear when the enumeration is complete.

0
Oct 24 '08 at 5:57
source share

IIRC. The thing is that IEnumerable<T> and IEnumerable are the result of IEnumerable , which precedes the .Net template material. I suspect your question is similar.

-2
Oct 24 '08 at 5:29
source share



All Articles