简体   繁体   中英

Early execution of IEnumerable

So I have two methods both performing iteration through IEnumerable collection.

    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;
            }
        }
    }

I recently came to know method returning IEnumerable will not execute until enumerated.

So I created two blocks of code to call each method

Calling 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

But, in the case of GetRangeFunction , the method is called right away on creating the iterator.

var iterator = GetRangeFunction(0, 5);

Why is this behaviour? I was thinking GetRangeFunction also, won't execute until an item is requested.

EDIT

My question is poorly stated, let me try to explain it one more time.

Both the enumerators are returning items via yield one after other. But in the case of GetRange , no statement ( not even checking count is less than zero ) is executed until any operation is done on the enumerator. But, in case of GetRangeFunction the condition check is executed when the method is called to create the iterator.

According to MSDN , local function can allow exceptions to surface immediately. For example, consider the following code.

        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;
            }
        }

To make sure local method version can get exception quickly, GetNumberByLocalMethod version will execute immediately and not wait until the first iterate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM