Consider the following code, the first demonstrates that the “cleanup” executes when we’re finished iterating over the IEnumerable of strings. The second pass is what is causing me grief. I need to be able abandon the IEnumerable before reaching the end, and then have the clean up code execute. But if you run this you’ll see that in the second pass the clean up never fires.
What is the preferred way of abandoning an IEnumerable like this?
static void Main(string[] args)
{
// first pass
foreach (String color in readColors())
Console.WriteLine(color);
// second pass
IEnumerator<string> reader = readColors().GetEnumerator();
if (reader.MoveNext())
{
Console.WriteLine(reader.Current);
reader.Dispose();
}
}
static IEnumerable<string> readColors()
{
string[] colors = { "red", "green", "blue" };
for (int i = 0; i < colors.Length; i++)
yield return colors[i];
Console.WriteLine("Cleanup goes here");
}
You need to put the main part of your iterator method into a try..finally, with the cleanup code in the finally:
Remember that under the hood an iterator method causes a seperate class to be created, that implements
IEnumerableandIEnumerator. By putting your cleanup in the finally block, it ends up in the generated class’Disposemethod.[Edit: (as pointed out in other answers) prefer a
usingstatement over your approach of callingDisposemanually. I was assuming you’d done it like this just to highlight the issue under discussion, but it is worth pointing out anyway]