提前执行IEnumerable

时间:2019-02-18 13:44:05

标签: c# .net .net-core ienumerable

所以我有两种方法都通过IEnumerable集合执行迭代。

    public static IEnumerable<int> GetRange(int start, int count)
    {
        if (count < 0)
            throw new ArgumentOutOfRangeException(nameof(count));

        var end = start + count;

        for (int value = start; value < end; value++)
        {
            yield return value;
        }
    }


    public static IEnumerable<int> GetRangeFunction(int start, int count)
    {
        if (count < 0)
            throw new ArgumentOutOfRangeException(nameof(count));

        var end = start + count;
        return RangeEnumeration();

        //Using local function
        IEnumerable<int> RangeEnumeration()
        {
            for (var value = start; value < end; value++)
            {
                yield return value;
            }
        }
    }

我最近才知道返回IEnumerable的方法直到被枚举才执行。

所以我创建了两个代码块来调用每个方法

调用GetRange

var iterator = GetRange(0, 10); // This does not start the execution of `GetRange` method. Instead, it waits till any item is requested
foreach(var item in iterator) //Now the GetRange method is called
{

}

GetRangeFunction

但是,在GetRangeFunction的情况下,该方法会在创建迭代器时立即调用。

var iterator = GetRangeFunction(0, 5);

为什么这是行为?我还以为GetRangeFunction直到请求一个项目才执行。

编辑

我的问题讲得不好,让我再解释一次。

两个枚举器都通过yield彼此返回项。但是对于 GetRange ,在对枚举数进行任何操作之前,不会执行任何语句(not even checking count is less than zero)。但是,如果使用 GetRangeFunction ,则在调用该方法以创建迭代器时执行条件检查。

1 个答案:

答案 0 :(得分:2)

根据MSDN,局部函数可以使异常立即浮出水面。例如,考虑以下代码。

        static void Main()
        {            
            IEnumerable<int> ienum = GetNumber(50, 110);
            //below line will not execute if use GetNumberByLocalMethod
            Console.WriteLine("Retrieved enumerator...");

            foreach (var i in ienum)
            {
                Console.Write($"{i} ");
            }
        }

        public static IEnumerable<int> GetNumberByLocalMethod(int start, int end)
        {
            throw new Exception("deliberately exception");
            return InnerGetNumberByLocalMethod();
            IEnumerable<int> InnerGetNumberByLocalMethod()
            {
                for (int i = start; i <= end; i++)
                {                    
                        yield return i;
                }
            }
        }

        public static IEnumerable<int> GetNumber(int start, int end)
        {
            throw new Exception("deliberately exception");

            for (int i = start; i <= end; i++)
            {                
                    yield return i;
            }
        }

为确保本地方法版本可以快速获取异常,GetNumberByLocalMethod版本将立即执行,而不必等到第一次迭代。