-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Labels
area-System.Linqhelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributors
Milestone
Description
It is my understanding that LINQ should always call IEnumerator's Dispose method when finished with an IEnumerator. I've found a case where this does not happen: Take two IEnumerators that immediately return false in their MoveNext() implementations (i.e. they are empty), Union them and then perform a Select on that. Here is a minimal reproduction that shows Dispose() is not called for either IEnumerator. This reproduces in dotnet core 2.1 & 2.2. It does not reproduce in .NET Framework 4.7.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.
Metadata
Metadata
Assignees
Labels
area-System.Linqhelp wanted[up-for-grabs] Good issue for external contributors[up-for-grabs] Good issue for external contributors