👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
Understanding LINQ Deferred, Immediate, Streaming and Non-Streaming Executions

Understanding LINQ Deferred, Immediate, Streaming and Non-Streaming Executions

LINQ

26 Articles

Improve

In this article, let's learn about how Execution and Operators works in LINQ in .NET.

Note: If you have not done so already, I recommend you read the article on Using LINQ For Each to iterate Collections.

Table of Contents

  1. Introduction
  2. Immediate Execution
  3. Deferred Execution
  4. Streaming Operators
  5. Non-Streaming Operators
  6. Classification Table
  7. Summary

Introduction

LINQ to Objects has two ways of running its standard query operator methods: right away or later on. When using the later option, it can either stream the data or not. Knowing which option you're using can help you understand the results you get from your query, especially if the data is changing or if you're building a query on top of another one. This topic organizes the standard query operators by how they work.

LINQ has four Manners of Execution. They are,

  • Immediate
  • Deferred
  • Streaming
  • Non-Streaming
LINQ Execution Strategy

Understanding LINQ Execution Manners and Operators has the following advantages

  • Better Performance.
  • Less Iterations.

Immediate Execution

Immediate execution in LINQ to Objects means that the data is read and the operation is done right away. Standard query operators that return a single / scalar value always work this way. You can make a query execute immediately by using either Enumerable.ToList() or Enumerable.ToArray() methods. Immediate execution helps you save time by reusing the results of your query instead of running it again. The query results are stored for later use after being retrieved once.

Code Sample - LINQ Immediate Execution

Demo Space

Deferred Execution

Deferred execution in LINQ to Objects means that the query doesn't run when it's defined in the code. Instead, it runs only when you actually use the query results, for example in a foreach statement. This means that the query results can change depending on what's in the data source at the time the query is used, not when it's written. If you use the query results multiple times, you might get different results each time. Most standard query operators that return IEnumerable<T> or IOrderedEnumerable<TElement> work this way. Deferred execution lets you reuse queries, and it fetches updated data from the data source each time you iterate through the query results.

Query operators that use deferred execution can also be divided into two types: streaming and non-streaming.

Code Sample - Deferred Execution

Demo Space

Streaming Operators

Streaming operators in LINQ to Objects don't need to read all the source data before they start returning elements. Instead, they work on each source element one at a time and return the result immediately if applicable. A streaming operator keeps reading source elements until it can produce a result element. This means that sometimes it has to read more than one source element to make one result element.

Code Sample - LINQ Streaming Operators

Demo Space

Non-Streaming Operators

Non-streaming operators in LINQ to Objects need to read all the source data before they can start returning (yielding) any result elements. Sorting and grouping are examples of non-streaming operators. When a non-streaming operator runs, it reads all the source data, puts it into a data structure, performs the operation, and then returns (yields) the resulting elements.

Code Sample - LINQ Non-Streaming Operators

Demo Space

Classification Table

The following table classifies each standard query operator method according to its method of execution.

Manner of Execution Query Operators
Immediate Execution Aggregate, All, Any, Average, Cast, Concat, Contains, Count, DefaultIfEmpty, Distinct, ElementAt, ElementAtOrDefault, Except, First, FirstOrDefault, GroupBy (with overload), GroupJoin, Intersect, Join, Last, LastOrDefault, LongCount, Max, Min, OfType, OrderBy, OrderByDescending, Range, Repeat, Reverse, Select, SelectMany, SequenceEqual, Single, SingleOrDefault, Skip, SkipWhile, Sum, Take, TakeWhile, ThenBy, ThenByDescending, ToArray, ToDictionary, ToList, Union, Where, Zip
Deferred Execution - Streaming AsEnumerable, AsQueryable, Cast, Concat, DefaultIfEmpty, Distinct, GroupBy (without overload), Join, OfType, Reverse, Select, SelectMany, Take, TakeWhile, Union, Where
Deferred Execution - Non-Streaming Aggregate, All, Any, Average, Contains, Count, ElementAt, ElementAtOrDefault, Except, First, FirstOrDefault, GroupBy (with overload), GroupJoin, Intersect, Last, LastOrDefault, LongCount, Max, Min, OrderBy, OrderByDescending, Single, SingleOrDefault, Skip, SkipWhile, Sum, ThenBy, ThenByDescending, ToArray, ToDictionary, ToList, Zip

Summary

In this article we learn't how LINQ Execution and Operators work. We saw how Deferred and Immediate execution works along with Streaming and Non-Streaming operators. We learnt the advantages of deferred execution and how to use yield keyword in streaming operations with a live demo. With this I'm completing my LINQ series. Feel free to checkout LINQ learning path in LINQ Channel.

👉🏼 Click here to Join I ❤️ .NET WhatsApp Channel to get 🔔 notified about new articles and other updates.
  • LINQ
  • Deferred
  • Immediate
  • Streaming
  • Non-Streaming
  • Execution
  • Operators