C# iterator is executed twice when composing two IEnumerable methods

Posted by achristoph on Stack Overflow See other posts from Stack Overflow or by achristoph
Published on 2010-03-25T04:52:09Z Indexed on 2010/03/25 5:13 UTC
Read the original article Hit count: 291

Filed under:

I just started learning about C# iterator but got confused with the flow of the program after reading the output of the program. The foreach with uniqueVals seems to be executed twice. My understanding is that the first few lines up to the line before "Nums in Square: 3" should not be there. Can anyone help to explain why this happens?

The output is: Unique: 1 Adding to uniqueVals: 1 Unique: 2 Adding to uniqueVals: 2 Unique: 2 Unique: 3 Adding to uniqueVals: 3

Nums in Square: 3 Unique: 1 Adding to uniqueVals: 1 Square: 1 Number returned from Unique: 1 Unique: 2 Adding to uniqueVals: 2 Square: 2 Number returned from Unique: 4 Unique: 2 Unique: 3 Adding to uniqueVals: 3 Square: 3 Number returned from Unique: 9

static class Program
    {
      public static IEnumerable<T> Unique<T>(IEnumerable<T> sequence)
        {
            Dictionary<T, T> uniqueVals = new Dictionary<T, T>();

            foreach (T item in sequence)
            {
                Console.WriteLine("Unique: {0}", item);
                if (!uniqueVals.ContainsKey(item))
                {
                    Console.WriteLine("Adding to uniqueVals: {0}", item);
                    uniqueVals.Add(item, item);
                    yield return item;
                    Console.WriteLine("After Unique yield: {0}", item);
                }
            }
        }

        public static IEnumerable<int> Square(IEnumerable<int> nums)
        {
            Console.WriteLine("Nums in Square: {0}", nums.Count());
            foreach (int num in nums)
            {
                Console.WriteLine("Square: {0}", num);
                yield return num * num;
                Console.WriteLine("After Square yield: {0}", num);
            }
        }

        static void Main(string[] args)
        {
            var nums = new int[] { 1, 2, 2, 3 };
            foreach (int num in Square(Unique(nums)))
                Console.WriteLine("Number returned from Unique: {0}", num);
            Console.Read();
        }

    }

© Stack Overflow or respective owner

Related posts about c#