Get up to 80 % extra points for free! More info:

Lesson 9 - LINQ operators in C# .NET

In the previous lesson, LINQ providers, anonymous types, grouping and sorting in C#, we learned about anonymous types in LINQ and made examples for basic sorting and grouping.

We're already familiar with basic LINQ query syntax. In the next couple of articles, we're going to go over everything that LINQ has to offer. This will mainly include methods, more precisely operators, which you can use in your queries. We'll demonstrate everything with simple examples. The first few examples will be a bit repetitive. Then, once we have a good understanding of the concepts, we'll push our LINQ skills to new dimensions.

Restriction operators

We can specify a condition in any query and only select data when it meets said condition. We're already familiar with the where operator, which is a restriction operator.

Where

Where allows us to only select the data that fulfills a specific condition. Let's select all numbers greater than 5 from a given number sequence:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = from n in numbers
            where (n > 5)
            select n;

The query will select:

Console application
8
9

Indexed where

We have yet to try to access the item index in the where clause. Let's select the numbers that have the same value as the array index they're stored at:

int[] numbers = { 0, 5, 2, 5, 4, 1, 3, 7 };

var query = numbers.Where((number, index) => number == index);

The query will select:

Console application
0
2
4
7

In case you didn't notice, we used method syntax here. Some operators can't be written in any other way and don't support the LINQ SQL-like syntax (we'll see more of them later on).

Projection operators

We don't have to take the selected items as they are. In fact, we're able to select them solely by their property.

Select

Using select, we are able to specify what we're interested in from the resulting elements. Let's return double its amount for any number that's greater than 5:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = from n in numbers
            where (n > 5)
            select n * 2;

The query will select:

Console application
16
18

We can map a property or a method result in the same way, e.g. Length() or ToLower() on strings:

string[] words = { "SOcial", "nEtwork", "ICT" };

var query = from w in words
            select w.ToLower();

The query will select:

Console application
social
network
ict

Indexed select with anonymous types

Just like with where, the select operator gives us access to an element's index. We went over anonymous types in the previous lesson. Now, we'll show you all how to select an anonymous type which contains the position and the value for certain elements:

int[] numbers = { 3, 5, 8, 5 };

var query = numbers.Select((number, index) => new { Index = index, Value = number });

The query will select:

Console application
{ Index = 0, Value = 3 }
{ Index = 1, Value = 5 }
{ Index = 2, Value = 8 }
{ Index = 3, Value = 5 }

Partitioning operators

The original collection can be separated so that we're only able to work with part of it.

Take

Take selects the first few elements of the collection and discards the rest. This example selects the first 3 numbers from an array:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.Take(3);

The query will select:

Console application
3
5
8

Take with a query

We can also call Take() on the LINQ query by putting it in parentheses:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = (from n in numbers
             where (n > 3)
             select n * 2).Take(3);

The query will select:

Console application
10
16
10

Skip

Skip does the opposite of Take, therefore, it selects all elements except for the first few, which will be skipped (as the name implies).

Let's select all of the numbers from the array except for the first 5:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.Skip(5);

The query will select:

Console application
1
3
4

We often use Skip and Take to select random elements:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };
Random r = new Random();

var query = numbers.Skip(r.Next(numbers.Length)).Take(1);

This query selects a random number from the array.

TakeWhile

We can select elements from the beginning of the collection until a certain condition is met. From that moment on, no other items will be added. Let's select the first few numbers that are greater than 2:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.TakeWhile(n => n > 2);

The query will select:

Console application
3
5
8
5
9

TakeWhile can also be indexed.

SkipWhile

As you may have guessed, we also have the SkipWhile method, which skips numbers until a certain condition is true after which it starts to add numbers to the result. This example skips the first few numbers that are greater than 2:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.SkipWhile(n => n > 2);

The query will choose:

Console application
1
3
4

SkipWhile can also be indexed.

Skip may be (like any similar method) called on the LINQ query, just like in the Take example, we do so by putting the query into brackets. I won't state this anymore for other methods (take it for granted that this applies).

Sorting operators

We've already covered OrderBy, OrderByDescending, ThenBy, and ThenByDescending. Let's take a look at how we can sort results using Comparer.

OrderBy using Comparer

We can take advantage of comparers when we need to parametrize the query and change the criteria by which we're sorting, e.g. we let the user choose the criteria. First, it's important for us to declare our comparer. We'll use the string comparer in the example below, which compares strings and is case-sensitive:

public class CaseSensitiveComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        return string.Compare(x, y, StringComparison.Ordinal);
    }
}

Now let's put the comparer into a query:

string[] words = { "Argentina", "anaconda", "aLbert", "Buffalo", "business", "BOmb" };

var query = words.OrderBy(w => w, new CaseSensitiveComparer());
Console application
Argentina
BOmb
Buffalo
aLbert
anaconda
business

Set operators

We can treat a collection like a set (mathematical) and use the following operators to simplify our work:

Distinct

Distinct only selects unique elements from the collection. With that in mind, let's select all of the unique numbers from an array:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.Distinct();

The query will select:

Console application
3
5
8
9
1
4

Union

Union selects a union of 2 sets. Meaning that there it takes two collections as the input and the output is a set (collection) containing all of the elements of both of the input collections without repeating any of the elements. Let's try it out:

int[] set1 = { 3, 5, 8, 5, 9, 1, 3, 4 };
int[] set2 = { 3, 7, 2, 1, 4 };

var query = set1.Union(set2);

The query will select:

Console application
3
5
8
9
1
4
7
2

Intersect

Intersect selects an intersect of two sets. It takes two collections as the input and the output is a set (collection) containing only the elements that are common for both input collections. Let's try it out:

int[] set1 = { 3, 5, 8, 5, 9, 1, 3, 4 };
int[] set2 = { 3, 7, 2, 1, 4 };

var query = set1.Intersect(set2);

The query will select:

Console application
3
1
4

Except

The Except() method allows us to create a sequence containing the values of the first set that don't occur in the second set.

int[] set1 = { 3, 5, 8, 5, 9, 1, 3, 4 };
int[] set2 = { 3, 7, 2, 1, 4 };

var query = set1.Except(set2);

The query will select:

Console application
5
8
9

In the next lesson, More on LINQ operators, we'll continue learning about LINQ operators. You'll see just how much there is to LINQ :)


 

Previous article
LINQ providers, anonymous types, grouping and sorting in C#
All articles in this section
Collections and LINQ in C# .NET
Skip article
(not recommended)
More on LINQ operators
Article has been written for you by David Capka Hartinger
Avatar
User rating:
2 votes
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities