In a method returning IEnumerable<>
, I'm opening and looping over a resource (e.g. a database row reader). Once the loop finished, the resource is closed again.
However, it may happen that the caller decides not to finish the enumeration. This leaves the resource open.
Example:
IEnumerable<Foo> Bar ()
{
using (var r = OpenResource()) {
while (r.Read ()) {
yield return r;
}
}
}
// OK - this closes the resource again
foreach (var foo in Bar()) {
Console.WriteLine (foo);
}
// Not OK - resource stays open!
Console.WriteLine (Bar().First());
How would I solve this? Can I easily cancel an enumeration, i.e. tell it to skip over the rest of the loop, or dispose it (putting the cleanup code in Dispose
)?
I considered returning a Func<Result, bool>
so the user can have it return false
if he's done with iterating. Similarly, some kind of cancel token could be used, too. But both approaches seem cumbersome to me.
break;
should cancel it and the generated code should dispose of the enumerator. if the source doesn't do things properly, then that needs fixed.