Why use the yield keyword, when I could just use an ordinary IEnumerable?

前端 未结 8 1274
渐次进展
渐次进展 2020-12-22 15:08

Given this code:

IEnumerable FilteredList()
{
    foreach( object item in FullList )
    {
        if( IsItemInPartialList( item ) )
                 


        
      
      
      
8条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-22 15:36

    The benefit of iterator blocks is that they work lazily. So you can write a filtering method like this:

    public static IEnumerable Where(this IEnumerable source,
                                       Func predicate)
    {
        foreach (var item in source)
        {
            if (predicate(item))
            {
                yield return item;
            }
        }
    }
    

    That will allow you to filter a stream as long as you like, never buffering more than a single item at a time. If you only need the first value from the returned sequence, for example, why would you want to copy everything into a new list?

    As another example, you can easily create an infinite stream using iterator blocks. For example, here's a sequence of random numbers:

    public static IEnumerable RandomSequence(int minInclusive, int maxExclusive)
    {
        Random rng = new Random();
        while (true)
        {
            yield return rng.Next(minInclusive, maxExclusive);
        }
    }
    

    How would you store an infinite sequence in a list?

    My Edulinq blog series gives a sample implementation of LINQ to Objects which makes heavy use of iterator blocks. LINQ is fundamentally lazy where it can be - and putting things in a list simply doesn't work that way.

提交回复
热议问题