7. LINQ


What is LINQ? (C# 3.0+)

LINQ = Language Integrated Query

Definition: Query collections using SQL-like syntax directly in C#.

Benefits:

  • Type-safe queries - Compile-time checking

  • IntelliSense support - Auto-completion

  • Consistent syntax - Same queries for arrays, lists, databases, XML

  • Readable code - Declarative instead of imperative

  • Powerful operations - Filter, sort, group, join with minimal code

LINQ Providers

LINQ to Objects - Query in-memory collections (arrays, lists, etc.)

int[] numbers = { 1, 2, 3, 4, 5 };
var evens = numbers.Where(n => n % 2 == 0);

LINQ to SQL - Query SQL Server databases

var customers = from c in db.Customers
                where c.City == "London"
                select c;

LINQ to Entities (Entity Framework) - Query databases via EF

LINQ to XML - Query XML documents


Query Syntax vs Method Syntax

Side-by-Side Comparison

When to Use Each

Query Syntax:

  • ✅ More readable for complex queries with joins/grouping

  • ✅ Familiar to SQL developers

  • ✅ Better for multiple operations

  • ❌ Doesn't support all LINQ operators

Method Syntax:

  • ✅ Supports all LINQ operators

  • ✅ Can chain easily

  • ✅ Better for single operations

  • ✅ More flexible

Recommendation: Use method syntax (it's more common in modern C#)

Mixing Both Syntaxes


LINQ Operators by Category

1. Filtering Operators

Where - Filter elements

OfType<T> - Filter by type


2. Projection Operators

Select - Transform elements

SelectMany - Flatten nested collections


3. Sorting Operators

OrderBy / OrderByDescending

ThenBy / ThenByDescending - Secondary sort

Reverse - Reverse order


4. Grouping Operators

GroupBy - Group by key

ToLookup - Create lookup dictionary


5. Join Operators

Join - Inner join

GroupJoin - Left outer join

Zip - Combine two sequences


6. Set Operators

Distinct - Unique elements

Union - Combine sets (distinct)

Intersect - Common elements

Except - Difference


7. Quantifier Operators

Any - At least one matches

All - All match

Contains - Specific element exists


8. Aggregation Operators

Count / LongCount

Sum

Average

Min / Max

Aggregate - Custom aggregation


9. Element Operators

First / FirstOrDefault

Last / LastOrDefault

Single / SingleOrDefault

ElementAt / ElementAtOrDefault

DefaultIfEmpty


10. Generation Operators

Range - Sequence of integers

Repeat - Repeat value

Empty - Empty sequence


11. Partitioning Operators

Take / Skip

TakeWhile / SkipWhile

TakeLast / SkipLast (C# 6.0+)

Chunk (C# 6.0+)


12. Conversion Operators

ToArray / ToList (Immediate Execution!)

ToDictionary

ToLookup

ToHashSet (C# 7.3+)

AsEnumerable / AsQueryable

Cast<T>


13. Concatenation Operators

Concat

Append / Prepend (C# 7.3+)


14. Equality Operator

SequenceEqual


Deferred vs Immediate Execution

Deferred Execution (Lazy Evaluation)

Most LINQ operators use deferred execution - query is not executed until you iterate.

Deferred Operators: Where, Select, OrderBy, GroupBy, Join, Take, Skip, etc.

Immediate Execution (Eager Evaluation)

Some operators execute immediately - query runs when called.

Immediate Operators: ToArray, ToList, ToDictionary, ToHashSet, Count, Sum, Average, Min, Max, First, Last, Single, Any, All

Execution Behavior Table

Category
Deferred
Immediate

Filtering

Where, OfType

-

Projection

Select, SelectMany

-

Sorting

OrderBy, ThenBy

-

Grouping

GroupBy

ToLookup

Join

Join, GroupJoin

-

Set

Distinct, Union, Intersect

-

Partitioning

Take, Skip, TakeWhile

-

Conversion

Cast, AsEnumerable

ToArray, ToList, ToDictionary

Element

DefaultIfEmpty

First, Last, Single, ElementAt

Quantifier

-

Any, All, Contains

Aggregation

-

Count, Sum, Average, Min, Max

Multiple Enumeration Warning


Let Clause (Query Syntax)

Creates intermediate variables in query.


Into Clause (Query Syntax)

Continues query after grouping or joining.


Performance Considerations

1. Multiple Enumeration

2. ToList() Timing

3. LINQ vs foreach

4. Avoid Unnecessary Operations


Common LINQ Patterns

Pattern 1: Filtering and Projecting

Pattern 2: Grouping and Aggregating

Pattern 3: Joining Collections

Pattern 4: Pagination

Pattern 5: Distinct Values from Property

Pattern 6: Top N Items

Pattern 7: Conditional Filtering

Pattern 8: Flattening Nested Data


LINQ Quick Reference Table

Category
Operator
Purpose
Example

Filter

Where

Filter by condition

Where(n => n > 5)

OfType

Filter by type

OfType<int>()

Project

Select

Transform

Select(n => n * 2)

SelectMany

Flatten

SelectMany(o => o.Items)

Sort

OrderBy

Sort ascending

OrderBy(p => p.Name)

OrderByDescending

Sort descending

OrderByDescending(p => p.Price)

ThenBy

Secondary sort

ThenBy(p => p.Age)

Reverse

Reverse order

Reverse()

Group

GroupBy

Group by key

GroupBy(p => p.Category)

ToLookup

Group immediately

ToLookup(p => p.City)

Join

Join

Inner join

Join(orders, c=>c.Id, ...)

GroupJoin

Left outer join

GroupJoin(...)

Zip

Combine pairs

Zip(other)

Set

Distinct

Unique

Distinct()

Union

Combine (unique)

Union(other)

Intersect

Common

Intersect(other)

Except

Difference

Except(other)

Quantify

Any

Has matching

Any(n => n > 5)

All

All match

All(n => n > 0)

Contains

Has element

Contains(5)

Aggregate

Count

Count

Count()

Sum

Total

Sum()

Average

Average

Average()

Min/Max

Min/Max

Min(), Max()

Aggregate

Custom

Aggregate((a,b) => a+b)

Element

First

First element

First()

FirstOrDefault

First or default

FirstOrDefault()

Last

Last element

Last()

Single

Exactly one

Single()

ElementAt

At index

ElementAt(3)

Generate

Range

Int sequence

Range(1, 10)

Repeat

Repeat value

Repeat("x", 5)

Empty

Empty sequence

Empty<int>()

Partition

Take

First n

Take(5)

Skip

Skip n

Skip(10)

TakeWhile

Take while true

TakeWhile(n => n < 100)

Chunk

Split chunks

Chunk(10)

Convert

ToArray

To array

ToArray()

ToList

To list

ToList()

ToDictionary

To dict

ToDictionary(k => k.Id)

ToHashSet

To set

ToHashSet()

Concat

Concat

Concatenate

Concat(other)

Append

Add to end

Append(item)

Prepend

Add to start

Prepend(item)

Equal

SequenceEqual

Compare

SequenceEqual(other)

⚡ = Immediate execution (all others are deferred)


Top 20 Most-Used LINQ Operators

  1. Where - Filter elements

  2. Select - Transform elements

  3. FirstOrDefault - Get first or default

  4. ToList - Materialize to list

  5. OrderBy - Sort ascending

  6. Any - Check if any match

  7. Count - Count elements

  8. Sum - Total values

  9. GroupBy - Group by key

  10. Distinct - Unique elements

  11. Take - First n elements

  12. Skip - Skip n elements

  13. Join - Inner join

  14. SelectMany - Flatten

  15. OrderByDescending - Sort descending

  16. Max - Maximum value

  17. Min - Minimum value

  18. Average - Average value

  19. All - Check all match

  20. Contains - Check contains


Common Pitfalls

1. Modifying Collection During Iteration

2. Forgetting ToList/ToArray

3. Using Single() Incorrectly

4. Unnecessary ToList Chains


Best Practices

1. Use Method Syntax (Modern Approach)

2. Materialize at the End

3. Use FirstOrDefault Over First

4. Prefer Any() Over Count() > 0

5. Use Specific Operators

6. Avoid Multiple Enumerations

7. Use LINQ for Readability


Decision Tree: Which LINQ Operator?


Guide Complete! This comprehensive LINQ guide covers all operators, patterns, and best practices. LINQ is one of the most powerful features in C# - master it and you'll write cleaner, more expressive code! 📘

Last updated