What is C# Deferred Execution and how do you do it?
Let’s start by understanding what NOT is a Deferred Execution. Let’s take an example method which returns a list of all odd numbers until a given limit.
The method can look like below -
public IEnumerable<int> GetOdds(int upperLimit)
{
var oddsList = new List<int>();
for(int i = 1; i <= upperLimit; i++)
{
oddsList.Add(i);
}
return oddsList;
}
foreach(var element in GetOdds(50))
{
// the function is already executed
// and all the odd numbers untill 50
// are available in memory at this point
// this is Eager Execution
}
While the above logic works fine, it is not so optimized in terms of performance. This is because we are creating a new List and copying over the elements into that list. This means the control doesn’t come back until the entire list is processed. This is called Eager Execution.
This can have a performance hit, when dealing with a very large collection. This is where Deferred Execution helps.
In Deferred Execution, the evaluation of an expression is delayed until the point where its resultant value is actually used. That means in the above code, the list is actually prepared only when it is accessed somewhere.
In C#, deferred execution can be created by using a yield keyword, while returning a collection. The requirement is that the return type of method where yield keyword is used must be of type IEnumerator or IEnumerable.
The above function can be rewritten as below -
public IEnumerable<int> GetOdds(int upperLimit)
{
for(int i = 1; i <= upperLimit; i++)
{
if(i%2 != 0) yield return i;
}
}
foreach(var element in GetOdds(50))
{
// for every access of element in this block
// one single element is returned from the method
// this saves memory, and is faster
// this is Deferred Execution
}
#dotnetdeveloper #dotnet #csharp #performanceoptimization #memory #application #performance