收益率和动态

时间:2014-02-20 18:01:52

标签: c# .net

使用动态?

时可以调用“IEnumerable / yield return”方法

我问这个是因为当我调用“Test(States1.GetNames())”方法时,我收到了以下错误。

错误:“附加信息:'对象'不包含'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);
            }
        }
    }
}

由于

2 个答案:

答案 0 :(得分:4)

问题是迭代器块实现使用显式接口实现来实现IEnumerable<T> ...并且显式接口实现通常不能很好地与动态类型一起使用。 (您不需要使用迭代器块来查看它。有关详细信息,请参阅my article on Gotchas in Dynamic Typing。)

您可以使用foreach进行迭代:

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

这有额外的好处,它将为您处理迭代器,您以前的代码没有这样做:)

或者,您为Iterate添加重载以获取IEnumerableIEnumerable<T>,并让Test内的执行时重载解析做正确的事(由于{{ 1}}也是state

答案 1 :(得分:0)

它失败是因为IEnumerable<string>代码生成的yieldexplicitly implements其接口(包括您尝试使用的GetEnumerator)。你可以这样调用这个方法:

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

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

或者,既然你因为任何原因我不需要dynamic,我可以在这里看到,也许只是:

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

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

或者

public static void Iterate<T>(IEnumerable<T> itemList)