ScottBK

Greetings.

I have a method that uses yield return to generate values for an IEnumerable, and also uses a using statement and a continue statement. These seem to not play well together, as the method is leaking system resources. I have isolated a test case, and it seems to me that Dispose() is not getting called when it should be. I suspect the compiler is generating incorrect code.

Here is a test program and some output. Why does the MyDisposable object with the value of 5 not get disposed I'm using Visual Studio 2005 SP1 and .NET 2.0.

If you replace the using statement with the equivalent try-finally code, the problem still exists.

I could not find an existing post or article about this issue. Is this known behavior

Thanks for any responses.

Scott

The code...

using System;
using System.Collections.Generic;
using System.Text;

namespace testusing {
class Program {
private class MyDisposable : IDisposable {
private int m_value;

public MyDisposable(int value) {

Console.WriteLine("Creating " + value);
m_value = value;
}

public void Dispose() {
Console.WriteLine("Disposing " + m_value);
}
}

static void Main(string[] args) {
Console.WriteLine("Starting loop");
foreach (int result in CountEm()) {
Console.WriteLine("Yielded " + result);
}
Console.WriteLine("End of loop. Press Enter.");
Console.ReadLine();
}

private static IEnumerable<int> CountEm() {
for (int i = 0; i < 10; i++) {
Console.WriteLine("About to create " + i);
using (MyDisposable d = new MyDisposable(i)) {
if (i == 5) {
continue;
}
yield return i;
}
}
}
}
}

The output...

Starting loop
About to create 0
Creating 0
Yielded 0
Disposing 0
About to create 1
Creating 1
Yielded 1
Disposing 1
About to create 2
Creating 2
Yielded 2
Disposing 2
About to create 3
Creating 3
Yielded 3
Disposing 3
About to create 4
Creating 4
Yielded 4
Disposing 4
About to create 5
Creating 5
About to create 6
Creating 6
Yielded 6
Disposing 6
About to create 7
Creating 7
Yielded 7
Disposing 7
About to create 8
Creating 8
Yielded 8
Disposing 8
About to create 9
Creating 9
Yielded 9
Disposing 9
End of loop. Press Enter.



Re: Visual C# Language Problem using "continue", "yield return", and "using" in the same method in C# 2.0.

Marcelo Guerra - MSFT

Hi Scott,

I agree that the behaviour doesn't seem right. The object should be disposed (that's the objective behind the "using" keyword).

I'll look into it and post again.





Re: Visual C# Language Problem using "continue", "yield return", and "using" in the same method in C# 2.0.

Marcelo Guerra - MSFT

Hi Scott,

This is a bug in the C# Compiler. It's already on the bugs to be fixed list. Meanwhile you'll have to use a workaround like changing the continue with an if

Thanks for letting as know of the problem





Re: Visual C# Language Problem using "continue", "yield return", and "using" in the same method in C# 2.0.

Matthew Watson

Good catch!

This workaround seems to work:



private static IEnumerable<int> CountEm()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("About to create " + i);
using (MyDisposable d = new MyDisposable(i))
{
if (i != 5)
{
yield return i;
}
}
}
}