We are trying to use an IEnumerable
as a factory that generates different objects each time we iterate over it. Those should be GC'ed as soon as possible. Note however that we keep a reference to the enumerator so we can call it again. So our program basically looks like this:
public class YieldSpec
{
public static IEnumerable<string> Strings()
{
yield return "AAA";
yield return "BBB";
yield return "CCC";
}
public void YieldShouldAllowGC()
{
var e = Strings();
foreach (var a in e)
{
Console.WriteLine(a);
}
}
}
Looking at that code in the debugger:
You can see that when the breakpoint is hit the IEnumerable has a reference to "CCC".
This shouldn't really happen. IEnumerable should only generate an IEnumerator when GetEnumerator is called. Is this expected behavior that IEnumerable can contain state?
As an implementation detail for performance reasons, yes, the state machine implements both IEnumerable
and IEnumerator
. That said, it is smart enough to do this correctly. It is only the very first time that the IEnumerable
is asked for an IEnumerator
that it returns itself. Any future calls to GetEnumerator
result in a new instance of the object being created, so that the separate iterator states can be maintained. This is done because while it is important to be able to have an IEnumerable
create multiple IEnumerators
, the vast majority of actual situations involve exactly one being created, so that's the situation that was optimized for.
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