C 🧠 LINQ in C#: Understanding Deferred Execution vs Immediate Evaluation

🧠 LINQ in C#: Understanding Deferred Execution vs Immediate Evaluation

LINQ is a powerful feature in C#, but it comes with nuances that can trip up even experienced developers — especially around deferred execution. Let’s dive into a real-world example that clearly shows the difference between deferred and immediate evaluation in LINQ.

Here’s the challenge:

class Patient
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }

    public static List<Patient> GetPatients()
    {
        List<Patient> patientList = new List<Patient>()
        {
            new Patient(){ ID = 1, Name = "John", Gender = "Male", Age = 20 },
            new Patient(){ ID = 2, Name = "Hanah", Gender = "Female", Age = 32 },
            new Patient(){ ID = 3, Name = "Timmy", Gender = "Male", Age = 55 },
            new Patient(){ ID = 4, Name = "Bella", Gender = "Female", Age = 68 }
        };
        return patientList;
    }
}

private class Program
{
    public static void Main(string[] args)
    {
        List<Patient> patientList = Patient.GetPatients();

        var filterList1 = patientList.Where(p => p.Age > 50).ToList();
        var filterList2 = patientList.Where(p => p.Age > 50);
        patientList[1].Age = 51;

        foreach (var patient in filterList2)
        {
            Console.WriteLine($"Patient ID : {patient.ID}  Patient Name : {patient.Name}");
        }

        Console.ReadKey();
    }
}

🔍 What Will Be Printed?

Let’s break it down step-by-step.

Initial Patient Data:

ID Name Age
1 John 20
2 Hanah 32
3 Timmy 55
4 Bella 68

Then we do the following:

 
 
var filterList1 = patientList.Where(p => p.Age > 50).ToList();
  • This executes immediately because of .ToList()

  • The result is:

    • Timmy (55)

    • Bella (68)

var filterList2 = patientList.Where(p => p.Age > 50);

This is a deferred query — it’s not executed until it's used

Then:

patientList[1].Age = 51; // Hanah is now 51

Now we loop over filterList2:

foreach (var patient in filterList2)

Since it’s deferred, it’s evaluated at this moment, meaning Hanah now qualifies as well.


✅ Final Output:

Patient ID : 2 Patient Name : Hanah
Patient ID : 3 Patient Name : Timmy
Patient ID : 4 Patient Name : Bella


🎯 Lesson: Deferred Execution vs Immediate Evaluation

This LINQ challenge is a textbook example of how timing affects query results in C#.

💡 Key Takeaways

  1. Deferred Execution

    • .Where(...) stores the logic but doesn’t run the query immediately

    • The data is evaluated only when the result is iterated over

  2. Immediate Evaluation

    • Using .ToList() or .ToArray() forces the query to run and materialize results at that moment

  3. Modifications to the Source Affect Deferred Queries

    • If the underlying list changes, so will the outcome of a deferred query

    • This can be useful — or it can cause unexpected bugs

  4. Use .ToList() for Snapshots

    • If you want to freeze the result for consistency, use .ToList() to prevent side effects from future changes


🧠 When Does This Matter?

This concept becomes important when working with:

  • UI-bound collections (like filtering a list in a data grid)

  • Long-running processes

  • Multi-threaded applications

  • Unit tests relying on expected values


Have you ever been caught off guard by deferred execution in LINQ? How do you approach query evaluation in your codebase?

💬 Drop your thoughts in the comments

 

 

Add comment