C# - An introduction to LINQ

In C#, LINQ (Language INtegrated Query) is a powerful tool for querying and manipulating data. LINQ provides an intuitive way to interact with various data sources, such as collections, databases, XML, and more. In this blog post we take a look at the key concepts, syntax, and benefits of LINQ.

What is LINQ?

LINQ is a query language extension that integrates query capabilities directly into C#. It allows developers to write queries against different data sources in the same way using a declarative manner. LINQ provides a seamless and efficient way to express queries, enabling data manipulation, filtering, sorting, and grouping operations.

All of LINQ methods are Extension methods from the System.Linq space.

LINQ Features and Benefits

Improved Maintainability
LINQ introduces a more readable and concise syntax for querying data, making code easier to understand and maintain. With LINQ, you can express complex queries in a more intuitive and natural manner. LINQ has many built-in and reusable functions making it easy to not repeat yourself, keeping the code DRY and thereby more maintainable.

For example if we want to count the numbers that are less than five in a list, we can use Count in combination with a lambda:

var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var count = numbers.Count(x => x < 5); // count is 4

The same without using LINQ (in combination with Lambda) takes multiple lines:

var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var count = 0;
foreach (var number in numbers)
    if (number < 5)
// count is 4

Type Safety for reduced runtime errors
One of the great advantages of LINQ is its strong typing. LINQ queries are checked at compile-time, ensuring type safety and reducing the risk of runtime errors. This enables early detection of issues and provides a robust development experience as it shortens the feedback loops.

Language Integration
You can leverage other parts of the C# language when making queries with LINQ. You can use familiar constructs such as lambda expressions, anonymous types, and extension methods to build sophisticated and flexible queries.

Querying Various Data Sources
LINQ supports querying a wide range of data sources, including in-memory objects, databases, XML documents, and web services. This enables developers to apply the same query syntax and techniques across different data contexts, enhancing code reuse and consistency.

LINQ Concepts

Query Expressions
LINQ query expressions provide a high-level and intuitive syntax for expressing queries. They resemble SQL-like statements and consist of clauses such as from, where, select, orderby, and groupby. These clauses are used to define the source of data, apply filters, project results, and sort or group data as needed.

Standard Query Operators
LINQ offers a rich set of standard query operators that can be used to perform various operations on data. These operators include filtering (Where), projection (Select), aggregation (Count, Sum, Average), sorting (OrderBy), grouping (GroupBy) etc. These operators can be combined to create complex queries tailored to specific requirements.

Deferred Execution
LINQ queries employ deferred execution, which means that the actual execution of the query is delayed until the query results are required. This deferred execution allows for optimization and efficiency by executing only the necessary operations and reducing unnecessary computations.

Most working with IEnumerables in for example Entity Framework will recognise that the execution is deferred until enumerated using GetEnumerator() ToList(), ToArray or similar. This means that the query or several queries are not executed for every expression or operator (.Where(), .Select(), Sum()etc.) but only when enumerated. Using ToList() and ToArray are known as immediate enumeration as they load the result into memory and thereby avoids multiple enumeration. Having several loops on the same IEnumerable can cause multiple enumeration, which is simply running the query multiple times.

Strongly Typed Results
LINQ queries return strongly typed results, meaning that the result objects have a specific type inferred from the query itself. This allows for compile-time checking and enables working with the results in a type-safe manner.

Difference between Lambda and LINQ

Lambda and LINQ are two distinct features in the C# programming language, but they are often used together to achieve powerful and concise code.

A lambda expression is an anonymous function that can be used to create delegates or expression trees. It provides a convenient way to write inline functions without explicitly defining a separate method. Lambda expressions are primarily used for functional programming and working with collections of data.

Here is an example that demonstrates LINQ querying a list of integers (LINQ Query):

var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7 8, 9 };
var count = (from num in numbers
             where num < 5
             select num).Count(); // count is 4

Here is the same using LINQ with a Lambda expression (LINQ Method):

var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var count = numbers.Count(x => x < 5); // count is 4

From the above we can see that Lambdas make the code more concise.

Some examples

Here are some examples of some different LINQ methods:

var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var numbersBelow5 = numbers.Where(x => x < 5); // returns a list of 4 items
var sum = numbers.Where(x => x < 5).Sum(); // sum is 10
var first = numbers.First(); //returns one item
var firstOrDefault = numbers.FirstOrDefault(x => x == 5); //firstOrDefault is 5

In the above we use Where to get items in a list based on a condition. We can combine this with Sum to sum all the numbers returned. Using First we can get the first item in the list and using FirstOrDefault with a lambda expression we can get an item based on a condition and if not present a default value instead.

That is all

I hope LINQ is more clear to you after reading this blog post. If so, or if this needs some corrections, please leave a comment down below with some feedback!