<Thanks>lbaker</Thanks>
<Test>IronPythonTest.ProtocolTest and test_cliclass.py (test_iterator_dispose)</Test>
Version: IronPython 2.6b2
In C# when executing a foreach statement on an IEnumerable, the Dispose() method is called on the
IEnumerator that is returned when execution leaves the foreach block regardless of whether by normal
control flow or exception.
In IronPython's for loop, however, the enumerator's Dispose() method does not seem to be called when
control flow exits the for loop early via an exception raised from the body of the loop. This can cause
resource leaks in the enumerator. eg if the enumerator holds onto a database connection, mutex, file handle, etc.
If the list part of the 'for' statement is an IEnumerable then the IEnumerator should probably be Dispose()d on termination of the 'for' loop.
Example:
// C# Resource
class Query : IDisposable
{
public Query() { System.Console.WriteLine("Query Created"); }
public void Dispose() { System.Console.WriteLine("Query Disposed"); }
public static IEnumerable<int> GetValues()
{
using (var query = new Query())
{
yield return 0;
}
}
}
// C# Test
public class Program
{
public static void Main()
{
try
{
foreach (var x in Query.GetValues())
{
System.Console.WriteLine("throwing");
throw new Exception();
}
}
catch
{
System.Console.WriteLine("caught");
}
}
}
Output:
Query Created
throwing
Query Disposed
caught
// Python Test
try:
for x in Query.GetValues():
print "raising"
raise Exception()
except:
print "caught"
Output:
Query Created
raising
caught
Expected Output:
Query Created
raising
Query Disposed
caught