LINQ's Distinct() Method Does Not Consume Its IEnumerable<T>

by Larry Spencer Wednesday, December 26, 2012 7:50 PM

You probably know that some of the LINQ methods that extend IEnumerable<T> cause the IEnumerable<T> to run to its end before they return anything. Count() and ToArray() are obvious examples. What about Distinct()? Will that begin to return items before the IEnumerable<T> has finished?

The answer is yes, and that can be very handy. I'm becoming more and more a fan of IEnumerable<T> because it feeds into so many things: LINQ, of course, but also Parallel.ForEach and other goodies.

Many collections not only derive from IEnumerable<T> but can also be constructed on an IEnumerable<T>s. IEnumerable<T> thus becomes like an intra-process pipe. (You'll be seeing some of this in the next couple of posts!) It's good to know that Distinct() plays nicely in all this goodness as it preserves the peel-off-as-needed spirit of IEnumerable<T>,

Here's an experiment that proves it.

 

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Enter values, one per line. A blank line ends the input.");

        var enumerable = new ConsoleEnumerable().Distinct();
        foreach (var line in enumerable)
        {
            Console.WriteLine("---> The next item in the enumeration is '{0}'", line);
        }
        Console.WriteLine("All done! Press Enter again to quit.");
        Console.ReadLine();
    }
}

class ConsoleEnumerable : IEnumerable<string>
{
    public IEnumerator<string> GetEnumerator()
    {
        while (true)
        {
            string line = Console.ReadLine();
            if (line.Length == 0)
                yield break;
            else
                yield return line;
        }
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

 

In this sample run, you can see that the distinct items came back as soon as they were available.

Tags:

All | General

About the Author

Larry Spencer

Larry Spencer develops software with the Microsoft .NET Framework for ScerIS, a document-management company in Sudbury, MA.