Skip to content

LINQ, Union followed by Select on empty IEnumerable fails to invoke Dispose #30607

@acolombi

Description

@acolombi

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

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions