1

According to the accepted answer to Enumerator disposal when not using using, foreach or manually calling Dispose() enumerators in C# must be disposed when finished with, whether you let foreach do this automatically, or do it yourself if you prefer to write out the equivalent logic by hand.

I wasn't expecting this; would have thought enumerators would be handled by the garbage collector. I'm guessing it's along the lines of:

  • Database queries are also enumerable, and those need to be disposed because they could be holding database connections, which are a scarcer resource than memory.

  • To correctly handle this case, the framework designers decided to just make enumerators implement IDisposable, so the contract is they should always be disposed; for in-memory collections like strings, arrays and lists, this will be a no-op, but it makes the overall design simpler than trying to make some kinds of enumerators implement a different interface.

Is this correct, or am I missing something?

rwallace
  • 31,405
  • 40
  • 123
  • 242
  • 8
    In short: yes. Of course enumerators are handled by the GC; `IDisposable` operates orthogonally to the GC and is explicitly for predictably cleaning up resources as soon as possible, instead of when the GC gets around to it. Aside from databases, think of things like file system enumerations that go across a network share. There are many use cases for enumeration that allocate unmanaged resources under the covers. – Jeroen Mostert Jun 03 '21 at 10:55
  • 1
    They *are* handled by the garbage collector. All objects are. The GC may take quite a long time to run though (several minutes if there's no memory pressure), and some resources are too expensive to keep active – Panagiotis Kanavos Jun 03 '21 at 10:56
  • 1
    Does this answer your question? [Do I need to consider disposing of any IEnumerable I use?](https://stackoverflow.com/questions/13459447/do-i-need-to-consider-disposing-of-any-ienumerablet-i-use) and [Why does IEnumerator inherit from IDisposable while the non-generic IEnumerator does not?](https://stackoverflow.com/questions/232558/why-does-ienumeratort-inherit-from-idisposable-while-the-non-generic-ienumerat) –  Jun 03 '21 at 11:09
  • 1
    As for the idea to use two interfaces (one implementing `IDisposable`, the other not); try writing out some code that would use an `IEnumerable` that conditionally returns either kind of enumerator, or tries to get an interface at runtime through reflection -- it's a lot of overhead just to avoid a `finally` block calling a method that would normally do nothing. (They actually made this mistake initially with the non-generic `IEnumerator`.) – Jeroen Mostert Jun 03 '21 at 11:12
  • 1
    @OlivierRogier The second one does, thanks! – rwallace Jun 03 '21 at 12:05

0 Answers0