Classification of Standard Query Operators by Manner of Execution

The LINQ to Objects implementations of the standard query operator methods execute in one of two main ways: immediate or deferred. The query operators that use deferred execution can be additionally divided into two categories: streaming and non-streaming. If you know how the different query operators execute, it may help you understand the results that you get from a given query. This is especially true if the data source is changing or if you are building a query on top of another query. This topic classifies the standard query operators according to their manner of execution.

Manners of Execution

Immediate

Immediate execution means that the data source is read and the operation is performed at the point in the code where the query is declared. All the standard query operators that return a single, non-enumerable result execute immediately.

Deferred

Deferred execution means that the operation is not performed at the point in the code where the query is declared. The operation is performed only when the query variable is enumerated, for example by using a foreach (For Each in Visual Basic) statement. This means that the results of executing the query depend on the contents of the data source when the query is executed rather than when the query is defined. If the query variable is enumerated multiple times, the results might differ every time. Almost all the standard query operators whose return type is IEnumerable<T> or IOrderedEnumerable<TElement> execute in a deferred manner.

Query operators that use deferred execution can be additionally classified as streaming or non-streaming.

Streaming

Streaming operators do not have to read all the source data before they yield elements. At the time of execution, a streaming operator performs its operation on each source element as it is read and yields the element if appropriate. A streaming operator continues to read source elements until a result element can be produced. This means that more than one source element might be read to produce one result element.

Non-Streaming

Non-streaming operators must read all the source data before they can yield a result element. Operations such as sorting or grouping fall into this category. At the time of execution, non-streaming query operators read all the source data, put it into a data structure, perform the operation, and yield the resulting elements.

Classification Table

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

Note

If an operator is marked in two columns, two input sequences are involved in the operation and each sequence is evaluated differently. In these cases, it is always the first sequence in the parameter list that is evaluated in a deferred, streaming manner.

Standard Query Operator

Return Type

Immediate Execution

Deferred Streaming Execution

Deferred Non-Streaming Execution

Aggregate

TSource

X

 

 

All<TSource>

Boolean

X

 

 

Any

Boolean

X

 

 

AsEnumerable<TSource>

IEnumerable<T>

X

 

Average

Single numeric value

X

 

 

Cast<TResult>

IEnumerable<T>

 

X

 

Concat<TSource>

IEnumerable<T>

 

X

 

Contains

Boolean

X

 

 

Count

Int32

X

 

 

DefaultIfEmpty

IEnumerable<T>

 

X

 

Distinct

IEnumerable<T>

 

X

 

ElementAt<TSource>

TSource

X

 

 

ElementAtOrDefault<TSource>

TSource

X

 

 

Empty<TResult>

IEnumerable<T>

X

 

 

Except

IEnumerable<T>

X

 X

First

TSource

X

 

 

FirstOrDefault

TSource

X

 

 

GroupBy

IEnumerable<T>

 

 

X

GroupJoin

IEnumerable<T>

X

Intersect

IEnumerable<T>

X

X

Join

IEnumerable<T>

X

X

Last

TSource

X

 

 

LastOrDefault

TSource

X

 

 

LongCount

Int64

X

 

 

Max

Single numeric value, TSource, or TResult

X

 

 

Min

Single numeric value, TSource, or TResult

X

 

 

OfType<TResult>

IEnumerable<T>

 

X

 

OrderBy

IOrderedEnumerable<TElement>

 

 

X

OrderByDescending

IOrderedEnumerable<TElement>

 

 

X

Range

IEnumerable<T>

 

X

 

Repeat<TResult>

IEnumerable<T>

 

X

 

Reverse<TSource>

IEnumerable<T>

 

 

X

Select

IEnumerable<T>

 

X

 

SelectMany

IEnumerable<T>

 

X

 

SequenceEqual

Boolean

X

 

 

Single

TSource

X

 

 

SingleOrDefault

TSource

X

 

 

Skip<TSource>

IEnumerable<T>

 

X

 

SkipWhile

IEnumerable<T>

 

X

 

Sum

Single numeric value

X

 

 

Take<TSource>

IEnumerable<T>

 

X

 

TakeWhile

IEnumerable<T>

 

X

 

ThenBy

IOrderedEnumerable<TElement>

 

 

X

ThenByDescending

IOrderedEnumerable<TElement>

 

 

X

ToArray<TSource>

TSource array

X

 

 

ToDictionary

Dictionary<TKey, TValue>

X

 

 

ToList<TSource>

IList<T>

X

 

 

ToLookup

ILookup<TKey, TElement>

X

 

 

Union

IEnumerable<T>

 

X

 

Where

IEnumerable<T>

 

X

 

See Also

Concepts

Standard Query Operators Overview

Query Expression Syntax for Standard Query Operators

LINQ to Objects

Reference

Enumerable