Just wondering why Enumerable.Range implements IDisposable.
I understand why IEnumerator<T> does, but IEnumerable<T> doesn't require it.
(I discovered this while playing with my .Memoise() implementation, which has statement like
if (enumerable is IDisposable)
((IDisposable)enumerable).Dispose();
in its "source finished" method that I had placed a breakpoint on out of curiousity, and was triggered by a test.)
Enumerable.Range uses yield return in its method body. The yield return statement produces an anonymous type that implements IDisposable, under the magic of the compiler, like this:
static IEnumerable<int> GetNumbers()
{
for (int i = 1; i < 10; i += 2)
{
yield return i;
}
}
After being compiled, there is an anonymous nested class like this:
[CompilerGenerated]
private sealed class <GetNumbers>d__0
: IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable
{
//the implementation
//note the interface is implemented explicitly
void IDisposable.Dispose() { }
}
so the result is a IDisposable. In this example, the Dispose method leaves empty. I think the reason is that there is nothing need to be disposed. If you yield return a type that contains unmanaged resources, you may get a different compiling result. (NOT SURE about it)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With