[Post-4][LINQ] Yield-Performance
Tags: csharp, dotnet, programming, 100daysofcode
Published: 2021-10-31 17:33:53


## [Post-4][LINQ] Yield-Performance

![](https://cdn-images-1.medium.com/max/2160/1*Tg6-0yVJkTZ1YzoXU36UoQ.gif)

Using yield return has a great performance benefit when querying the data. That is because, the data is returned only when it is iterated.

For example If you have to run multiple queries on a collection, one way is to iterate the collection for each query. The other way is to compile all the queries together and then run them once on the collection. The second way is better in performance and also has less memory footprint.

Lets look into an example to establish the above point. [Source code is provided in the end of the blog as a github gist]. In the example we will filter a list of numbers and get multiples of 6.

Below is the list of numbers from 1 to 20.

    List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

Lets do the filtering as a two step process.

 1. First we will filter the numbers that are divisible by **2**.

 2. Then, we will filter the numbers that are divisible by **3**.

Below are two functions bool DivideBy2(int x) and bool DivideBy3(int x) that return **true** if the number is divisible by **2 or 3 respectively**.

    private bool DivideBy2(int x)       
    {           
     if (x % 2 == 0)
     {                
       return true;         
     }           
     else 
     {               
       return false;           
     }       
    }

    private bool DivideBy3(int x)       
    {           
     if (x % 3== 0)
     {                
       return true;         
     }           
     else 
     {               
       return false;           
     }       
    }

Now lets create the a **Filter** extension on IEnumerable that filters the given enumerable based on a given predicate.

    public static IEnumerable<int> **FilterWithOutYield**(
    this IEnumerable<int> **enumerable**, Func<int, bool> **func**)        
    {
      IEnumerator<int> **enumerator **= enumerable.GetEnumerator();
      List<int> result = new List<int>();
      **while (enumerator.MoveNext())**
       {
          **if (func(enumerator.Current))**
          {
            **result.Add(enumerator.Current);**
          }
       }
      **return result as IEnumerable<int>;**
    }

The above function **FilterWithOutYield **has two parameters

 1. **enumerable**: The data on which this **FilterWithOutYield **is executed on.

 2. **func**: This function acts as a filter and helps decide whether the item filtered or not.

So the function is doing 3 things here

 1. Iterating over the **enumerable **in the while loop using its enumerator. [**while loop**]

 2. Filtering those numbers that satisfy the given predicate **func. **[**If **]

 3. Adding them to a list and returning them**. [result]**

Lets call the above **FilterWithOutYield **on the list of 20 numbers that we have created in the beginning.

    List<int> **numbers **= new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
                List<int> multiplesOfSix =
                    (
    numbers.FilterWithOutYield(**DivideBy2**) // returns a list 
           .FilterWithOutYield(**DivideBy3**) // returns a list

    ) as List<int>;

In the above code **FilterWithOutYield **is called ****twice on the numbers.

 1. First time, **DivideBy2 **is used as the predicate. The function filters all the numbers divisible by 2 and returns a list.

 2. Second time, **DivideBy3 **is used as the predicate. The function filters all the numbers divisible by 3 from the above list of numbers and returns another list.

At last a list of numbers that are divisible by 6 are returned. Here if you observe we are **iterating through the collection twice and returning a new List at each stage**.
>  I.e. If **FilterWithOutYield** is chained **n** times , the iterations are also proportionately increased and also the number of **lists** returned.

Now, lets look at a better way of doing the same using Yield. Below is the **FilterWithYield **function that filters an enumerable and uses ***yield return.***

    public static IEnumerable<int> FilterWithYield(
    this IEnumerable<int> enumerable, Func<int,bool> func)
    {
       IEnumerator<int> enumerator = enumerable.GetEnumerator();
       while (enumerator.MoveNext()) 
       {
         if (**func(enumerator.Current)**)
         {
           **yield return enumerator.Current;**
         }
       }
     }

If you note, in the above method we are not returning any list instead we are doing an **yield return.**

Lets call this method on an enumerable and see how it works.

    List<int> numbers = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };

    IEnumerable<int> multiplesOfSixUsingYield =
    numbers.FilterWithYield(**DivideBy2**) // The list is not iterated.
           .FilterWithYield(**DivideBy3**); //Instead enumerator is returned

The above code does not iterate over **numbers, **and therefore does not go into either of **DivideBy2 **or **DivideBy3 **methods. Instead an enumerator is created that uses both **DivideBy2 **and **DivideBy3 **methods to filter the enumerable.

To fetch a collection from the above code, the **multiplesOfSixUsingYield **has to be iterated using a ***foreach*** as below, or using extension methods like ***ToList() ***or ***ToArray()***.

    foreach (int x in multiplesOfSixUsingYield) 
    {              
       Console.WriteLine(x);
    }

Because of ***yield return***, the enumerable is iterated only once irrespective of the number of times the **FilterWithYield** method is used, improving the time and also decreasing the memory foot print.
{% gist https://gist.github.com/yashaswiyogeshwara/1523cddaeec9db1448b05f3a39b06078.js %}
Hope, you have liked the article. Keep reading. Thanks.