Common LINQ Operations
Learn to perform filtering, sorting, projection, and other common operations using LINQ query and method syntax.
We'll cover the following...
Most LINQ queries written using query syntax follow a predictable structure:
var result = from item in collectionselect item;
Line 1: We define the data source (
collection) and a range variable (item) that represents each individual element during iteration.Line 2: We use the
selectstatement to determine exactly what the query returns.
This basic syntax can be extended with filtering, sorting, projection, and other operations, which we explore individually.
Filter
To select items that match specific criteria, we use the where clause. After the where keyword, we provide a boolean expression that determines how the filtering occurs.
Line 1: We import the
System.Collections.Genericnamespace to access theList<T>collection type.Lines 4–7: We initialize a list of integers to serve as our data source.
Line 10: We apply the
whereclause with a condition that checks if the number is divisible by 2 with no remainder.Lines 13–16: We loop through the filtered sequence and print each even number to the console.
Order the output
We use the orderby and orderby descending clauses to sort the resulting collection. Here is how we apply them to our list of numbers.
Line 12: We use the
orderbykeyword to sort the results from smallest to largest, which is the default behavior.Line 18: We append the
descendingkeyword to theorderbyclause to reverse the sort direction.
Projection
So far, we have been selecting whole items from the collection. Projection enables customized selection. Instead of returning complete objects, we can choose specific properties and encapsulate them inside either a different class or an anonymous type.
First, we define our custom type using a file-scoped namespace.
Line 5: We initialize the
FullNameproperty withstring.Emptyto satisfy non-nullable reference type requirements and prevent compiler warnings.
With our data model ready, we can project specific properties into anonymous types within our main program logic.
Line 5: We import the
LinqQueriesnamespace to access our customEmployeemodel.Lines 18–21: We use the
select newsyntax to create an anonymous type containing only theSalaryandAgeproperties, discarding the rest of the employee data.
The let operator
We can also use the let keyword to perform operations and store the results in temporary variables inside the query itself.
To demonstrate this, we rely on the exact same Employee class defined in the previous section. Now we write a query that calculates a new salary for each employee and stores it in a temporary variable before projecting the final result.
Line 16: We use the
letkeyword to calculate a 15% salary increase and store it in theincreasedSalaryvariable.Lines 18–22: We project the result into a new, strongly typed
Employeeobject, passing ourincreasedSalaryvariable into theSalaryproperty.
Multiple sources
It is also possible to query several collections simultaneously. This approach yields all possible combinations of the elements from the specified collections, functioning similarly to a cross join in SQL.
We define two separate lists of strings and combine them in a single query.
Lines 15–16: We use two consecutive
fromclauses to query both thefirstNamesandlastNamescollections together.Line 17: We use string interpolation within the
selectstatement to combine the items into a single string.
Method syntax
Query syntax is not the only way to use LINQ. We can achieve the exact same results using extension methods, which we can call on any object that implements the IEnumerable interface.
These extension methods become available as soon as we connect to the System.Linq namespace. For instance, the where clause of the query syntax translates directly to the Where() method. We can apply this to our original list of numbers.
Line 9: We call the
Where()extension method directly on thenumberslist.
The Where() method accepts a delegate that takes an individual element of the collection and returns a bool value. In the code above, we supply a lambda expression that takes the number parameter and returns a boolean indicating whether it is divisible by two without a remainder.
Similar to the Where() method, there are OrderBy() and OrderByDescending() methods, among others.