Deferred Execution vs Immediate Execution in LINQ

Deferred Execution vs Immediate Execution in LINQ

In this article, I am going to discuss the difference between Deferred Execution vs Immediate Execution in LINQ with some examples. Please read our previous article where we discussed the LINQ Zip Method with an example. The LINQ queries are executed in two different ways as follows.

  1. Deferred execution
  2. Immediate execution

Based on the above two types of execution, the LINQ operators are divided into 2 categories. They are as follows:

  1. Deferred or Lazy Operators:  These query operators are used for deferred execution. For examples – select, SelectMany, where, Take, Skip, etc. are belongs to Deferred or Lazy Operators category.
  2. Immediate or Greedy Operators: These query operators are used for immediate execution. For Examples – count, average, min, max, First, Last, ToArray, ToList, etc. are belongs to Immediate or Greedy Operators category.
LINQ Deferred Execution:

In this case, the LINQ Query is not executed at the point of its declaration. That means, when we write a LINQ query, it doesn’t execute by itself. It executes only when we access the query results. So, here the execution of the query is deferred until the query variable is iterated over using for each loop.

Let us understand this with an example. The below example is self-explained. So, please go through the comment lines.

using System;
using System.Collections.Generic;
using System.Linq;

namespace LINQDemo
{
    public class Employee
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Salary { get; set; }
    }

    class Program
    {
        public static void Main()
        {
            List<Employee> listEmployees = new List<Employee>
            {
                new Employee { ID= 1001, Name = "Priyanka", Salary = 80000 },
                new Employee { ID= 1002, Name = "Anurag", Salary = 90000 },
                new Employee { ID= 1003, Name = "Preety", Salary = 80000 }
            };

            // In the below statement the LINQ Query is only defined and not executed
            // If the query is executed here, then the result should not display Santosh
            IEnumerable<Employee> result = from emp in listEmployees
                                           where emp.Salary == 80000
                                           select emp;

            // Adding a new employee with Salary = 80000 to the collection listEmployees
            listEmployees.Add(new Employee { ID = 1004, Name = "Santosh", Salary = 80000 });

            // The LINQ query is actually executed when we iterate thru using a for each loop
            // This is proved because Santosh is also included in the result
            foreach (Employee emp in result)
            {
                Console.WriteLine($" {emp.ID} {emp.Name} {emp.Salary}");
            }
            Console.ReadKey();
        }
    }
}

Output:

LINQ Deferred Execution in C#

Advantages of Deferred Execution:

We will get the following advantages

  1. It avoids the unnecessary query execution which improves the performance of the application.
  2. The Query creation and the Query execution are decoupled which provide us the flexibility to create the query in several steps.
  3. A Linq deferred execution query is always re-evaluated when we re-enumerate. As a result, we always get the updated data.
Immediate Execution

In the case of Immediate Execution, the LINQ query is executed at the point of its declaration. So, it forces the query to execute and gets the result immediately. Let us see an example for better understanding. The following example is self-explained. So, please go through the comment lines.

using System;
using System.Collections.Generic;
using System.Linq;

namespace LINQDemo
{
    public class Employee
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Salary { get; set; }
    }

    class Program
    {
        public static void Main()
        {
            List<Employee> listEmployees = new List<Employee>
            {
                new Employee { ID= 1001, Name = "Priyanka", Salary = 80000 },
                new Employee { ID= 1002, Name = "Anurag", Salary = 90000 },
                new Employee { ID= 1003, Name = "Preety", Salary = 80000 }
            };

            // In the following statement, the LINQ Query is executed immediately as we are
            // Using the ToList() method which is a greedy operator which forces the query 
            // to be executed immediately
            IEnumerable<Employee> result = (from emp in listEmployees
                                           where emp.Salary == 80000
                                           select emp).ToList();
            
            // Adding a new employee with Salary = 80000 to the collection listEmployees
            // will not have any effect on the result as the query is already executed
            listEmployees.Add(new Employee { ID = 1004, Name = "Santosh", Salary = 80000 });
            
            // The above LINQ query is executed at the time of its creation.
            // This is proved because Santosh is not included in the result
            foreach (Employee emp in result)
            {
                Console.WriteLine($" {emp.ID} {emp.Name} {emp.Salary}");
            }

            Console.ReadKey();
        }
    }
}

Output:

LINQ Immediate Execution in C#

Example:

In the following Immediate Execution example, we are using the greedy operator which returns a single value.

using System;
using System.Collections.Generic;
using System.Linq;

namespace LINQDemo
{
    public class Employee
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Salary { get; set; }
    }

    class Program
    {
        public static void Main()
        {
            List<Employee> listEmployees = new List<Employee>
            {
                new Employee { ID= 1001, Name = "Priyanka", Salary = 80000 },
                new Employee { ID= 1002, Name = "Anurag", Salary = 90000 },
                new Employee { ID= 1003, Name = "Preety", Salary = 80000 }
            };

            // In the following statement, the LINQ Query is executed immediately as we are
            // Using the Count() method which is a greedy operator which forces the query 
            // to be executed immediately
            var result = (from emp in listEmployees
                          where emp.Salary == 80000
                          select emp).Count();

            // Adding a new employee with Salary = 80000 to the collection listEmployees
            // will not have any effect on the result as the query is already executed
            listEmployees.Add(new Employee { ID = 1004, Name = "Santosh", Salary = 80000 });

            // The LINQ query is executed at the time of its creation.
            // This is proved because Santosh is not included in the count
            
            Console.WriteLine($" Employees with Salary 80000 : {result}");
            Console.ReadKey();
        }
    }
}

Output:

Deferred Execution vs Immediate Execution in LINQ

That’s it for today. In this article, I try to explain the difference between Deferred Execution vs Immediate Execution in LINQ with some examples. I hope you understood the Deferred and Immediate Execution in Linq. In the next article, I am going to discuss the ToList and ToArray method in C# with some examples.

Leave a Reply

Your email address will not be published. Required fields are marked *