Yield return and dynamic

Is possible to invoke a "IEnumerable/yield return" method when using dynamic?

I'm asking this because I'm getting the error below when I call the "Test(States1.GetNames())" method.

Error: "Additional information: 'object' does not contain a definition for 'GetEnumerator'"

using System;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;

namespace YieldDemo
{
    public class States1
    {
          public static IEnumerable<string> GetNames()
        {
            yield return "Alabama";
            yield return "Alaska";
            yield return "Arizona";
            yield return "Arkansas";
            yield return "California";
            yield return "Others ...";
        }
    }

    public class States2
    {
        private static readonly IList<string> _names;

        static States2()
        {
            _names = new List<string>() {"Alabama", 
                                     "Alaska",
                                     "Arizona",
                                     "Arkansas",
                                     "California",
                                     "Others ..." };

        }

        public static IList<string> GetNames()
        {
            return _names;
        }
    }

    public class Program
    {

        static void Main()
        {    
            Test(States2.GetNames());
            Test(States1.GetNames());

            Console.ReadLine();
        }

        public static void Test(dynamic state)
        {
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            Iterate(state);            
            stopwatch.Stop();

            Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
        }

        public static void Iterate(dynamic itemList)
        {
            var enumerator = itemList.GetEnumerator();

            while (enumerator.MoveNext())
            {
                Console.WriteLine(enumerator.Current);
            }
        }
    }
}

Thanks

Jon Skeet
people
quotationmark

The problem is that the iterator block implementation uses explicit interface implementation to implement IEnumerable<T>... and explicit interface implementation doesn't play nicely with dynamic typing in general. (You don't need to use iterator blocks to see that. See my article on Gotchas in Dynamic Typing for more details.)

You can iterate with foreach though:

public static void Iterate(dynamic itemList)
{
    foreach (dynamic item in itemList)
    {
        Console.WriteLine(item);
    }
}

This has the additional benefit that it will dispose of the iterator for you, which your previous code didn't do :)

Alternatively, you add overloads for Iterate to take IEnumerable or IEnumerable<T>, and let execution-time overload resolution within Test do the right thing (due to state being dynamic too).

people

See more on this question at Stackoverflow