C# Few good uses of yield keyword

T.Zacks 3,996 Reputation points
2022-10-13T12:59:04.037+00:00

I want to see few good uses of yield keyword.

1) i want to know the advantage of yield and when to use yield. please discuss with particular scenario.

2) How we can create custom enumarator using yield?

3)How do i understand that yield is lazy execution ? how can one say below code is a sample of yield lazy execution?

public static IEnumerable<int> CreateCollectionWithYield()  
{  
    yield return 10;  
    for (int i = 0; i < 3; i++)   
    {  
        yield return i;  
    }  

    yield return 20;  
}  
var yieldedItems = CreateCollectionWithYield();  

another sample

IEnumerable<T> FilterCollection<T>( ReadOnlyCollection<T> input ) {  
    foreach ( T item in input )  
        if (  /* criterion is met */ )  
            yield return item;  
}  

4) How yield maintain state ? in below code runningTotal variable set 0 once but RunningTotal() function calling repeatedly but runningTotal variable not initialize with 0 again.

how it is getting possible?

var vals = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };  

foreach (int e in RunningTotal())  
{  
    Console.WriteLine(e);  
}  

IEnumerable<int> RunningTotal()  
{  
    int runningTotal = 0;  

    foreach (int val in vals)  
    {  
        runningTotal += val;  
        yield return runningTotal;  
    }  
}  

Thanks

Developer technologies | C#
0 comments No comments
{count} votes

Accepted answer
  1. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2022-10-13T21:41:49.167+00:00

    If using .NET Core 5, Chunk internally uses yield. Try the following example here.

    using System;  
    using System.Collections.Generic;  
    using System.Globalization;  
    using System.Linq;  
    public class Program  
    {  
    	public static void Main()  
    	{  
            IEnumerable<string[]> chunk = DateTimeFormatInfo.CurrentInfo!.MonthNames[..^1].ToList().Chunk(2);  
            List<string[]> list = chunk.ToList();  
            for (int index = 0; index < list.LongCount(); index++)  
            {  
                Console.WriteLine(index);  
                foreach (var name in list[index])  
                {  
                    Console.WriteLine($"\t{name}");  
                }  
            }  
    	}  
    }  
    

    MS Code

    private static IEnumerable<TSource[]> ChunkIterator<TSource>(IEnumerable<TSource> source, int size)  
    {  
        using IEnumerator<TSource> e = source.GetEnumerator();  
        while (e.MoveNext())  
        {  
            TSource[] chunk = new TSource[size];  
            chunk[0] = e.Current;  
      
            int i = 1;  
            for (; i < chunk.Length && e.MoveNext(); i++)  
            {  
                chunk[i] = e.Current;  
            }  
      
            if (i == chunk.Length)  
            {  
                yield return chunk;  
            }  
            else  
            {  
                Array.Resize(ref chunk, i);  
                yield return chunk;  
                yield break;  
            }  
        }  
    }  
    

    Other uses, iterating a DataReader to return each item in the loop retrieving data.

    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,766 Reputation points Volunteer Moderator
    2022-10-13T21:08:46.363+00:00

    the yield is used for C# implementation of the common language (dates back to the 60's) feature: generator.

    https://en.wikipedia.org/wiki/Generator_(computer_programming)

    0 comments No comments

  2. Karen Payne MVP 35,586 Reputation points Volunteer Moderator
    2022-10-16T00:11:24.257+00:00

    This ^ is known as the hat operator.

    If we explore the hat operator with month names shown below, indexing the names we can use conventional indexing Start Index or in reverse with the hat operator via End Index

    250851-months.png

    This is the code to do what is shown above and most likely will invoke more questions as it's advance code so if there are questions, rather than ask questions perform your own research

    using System.Globalization;  
    using IndexMonths.Models;  
      
    namespace IndexMonths.Classes;  
      
    class Helpers  
    {  
        public static List<string> MonthNames() =>   
            DateTimeFormatInfo.CurrentInfo!.MonthNames[..^1].ToList();  
      
        public static List<ElementContainer<T>> RangeDetails<T>(List<T> list) =>  
            list.Select((element, index) => new ElementContainer<T>  
            {  
                Value = element,  
                StartIndex = new Index(index),  
                EndIndex = new Index(Enumerable.Range(0, list.Count).Reverse().ToList()[index], true),  
                MonthIndex = index + 1  
            }).ToList();  
    }  
    

    Calling the above

    using IndexMonths.Classes;  
      
    namespace IndexMonths  
    {  
        internal partial class Program  
        {  
            static void Main(string[] args)  
            {  
      
                var monthContainer = Helpers.RangeDetails(Helpers.MonthNames());  
                var table = CreateTable();  
                monthContainer.ForEach(x => table.AddRow(x.ItemArray));  
                  
                AnsiConsole.Write(table);  
      
                ExitPrompt();  
            }  
        }  
    }  
    

    Repository


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.