My understanding is that LINQ IEnumerable extensions are supposed to call Dispose on the IEnumerators produced by the IEnumerable. See this answer on SO. However, I'm not seeing that in practice. Is the other SO answer incorrect, or have I found a bug in LINQ?
Here's a minimal reproduction of the issue using Mono. It also reproduces in Dotnet Core 2.1 & 2.2.
using System;
using System.Threading;
using System.Linq;
using System.Collections.Generic;
using System.Collections;
namespace union
{
class MyEnumerable : IEnumerable<long>
{
public IEnumerator<long> GetEnumerator()
{
return new MyEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class MyEnumerator : IEnumerator<long>
{
public long Current
{
get
{
return 0;
}
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public bool MoveNext()
{
return false;
}
public void Reset()
{
return;
}
public void Dispose()
{
Console.WriteLine("I got disposed");
}
}
class Program
{
static void Main(string[] args)
{
var enum1 = new MyEnumerable();
var enum2 = new MyEnumerable();
enum1.Union(enum2).Select(x => x + 1).ToList();
Console.WriteLine("All done!");
}
}
}
If the Dispose was getting called you would see I got disposed
twice on the console. Instead you get no I got disposed
s. The Union
and the Select
are required to reproduce the issue.
Any C# gurus know if I've hit a bug?
Update:
I believe this is a bug, and I've filed: https://github.com/dotnet/corefx/issues/40384.