Introduction
Language Integrated Query (LINQ) is a game-changer in C#. It brings SQL-like data querying capabilities directly into your C# code, making data manipulation more intuitive, type-safe, and readable.
In this article, you’ll learn,
- What LINQ is and why it’s useful
- The different types of LINQ
- Query Syntax vs Method Syntax
- Common and advanced LINQ methods (including Zip, Chunk, OfType, and SelectMany)
- Practical examples for each method
What is LINQ in C#?
LINQ (Language Integrated Query) is a powerful feature that lets you query data directly in C# using a clear, readable syntax.
With LINQ, you can query.
- Collections in memory (arrays, lists)
- Databases (via Entity Framework or LINQ to SQL)
- XML files
- Datasets
- Custom collections
This unifies how you interact with data; you write queries in C#, not SQL or XQuery.
Types of LINQ
LINQ Type |
Purpose |
LINQ to Objects |
Query in-memory collections like arrays and lists |
LINQ to SQL |
Query SQL Server databases |
LINQ to Entities |
Query databases using Entity Framework |
LINQ to XML |
Query and manipulate XML data |
LINQ to DataSet |
Query DataSets and DataTables in ADO.NET |
Query Syntax vs Method Syntax
LINQ offers two ways to write queries.
1. Query Syntax
Similar to SQL, it's best for simple queries.
var evenNumbers = from n in numbers
where n % 2 == 0
select n;
2. Method Syntax
Uses extension methods with lambdas, more flexible for complex queries.
var evenNumbers = numbers.Where(n => n % 2 == 0);
Both produce the same result; use what fits your style!
Essential LINQ Methods
Let’s break down the most commonly used LINQ methods, with clear explanations and examples.
1. Where
Filters elements by a condition.
var adults = people.Where(p => p.Age >= 18);
2. Select
Projects each element to a new form.
var names = people.Select(p => p.Name);
3. OrderBy / OrderByDescending
Sorts elements.
var sorted = people.OrderBy(p => p.Name);
var sortedDesc = people.OrderByDescending(p => p.Age);
4. ThenBy / ThenByDescending
For secondary sorting.
var sorted = people.OrderBy(p => p.LastName).ThenBy(p => p.FirstName);
5. GroupBy
Group elements by a key.
var grouped = people.GroupBy(p => p.Age);
foreach (var group in grouped)
{
Console.WriteLine($"Age: {group.Key}");
foreach (var p in group) Console.WriteLine($" - {p.Name}");
}
6. Join
Joins two collections based on matching keys.
var result = customers.Join(
orders,
c => c.Id,
o => o.CustomerId,
(c, o) => new { c.Name, o.OrderId }
);
7. Distinct
Removes duplicates.
var uniqueAges = people.Select(p => p.Age).Distinct();
8. Union, Intersect, Except
Set operations.
var combined = list1.Union(list2);
var common = list1.Intersect(list2);
var difference = list1.Except(list2);
9. Any / All
Check for matches.
bool hasAdults = people.Any(p => p.Age >= 18);
bool allAdults = people.All(p => p.Age >= 18);
10. First / FirstOrDefault / Single / SingleOrDefault
Fetch single elements.
var firstAdult = people.First(p => p.Age >= 18);
var maybeAdult = people.FirstOrDefault(p => p.Age >= 18);
11. Take / Skip
Useful for paging.
var page = people.Skip(10).Take(10);
Advanced LINQ Methods: Let’s cover some lesser-known but powerful LINQ methods.
12. Zip
Combines two sequences element-wise.
int[] numbers = { 1, 2, 3 };
string[] words = { "one", "two", "three" };
var zipped = numbers.Zip(words, (n, w) => $"{n} = {w}");
foreach (var item in zipped)
{
Console.WriteLine(item);
}
// Output:
// 1 = one
// 2 = two
// 3 = three
13. Chunk
Splits a sequence into chunks of a specified size. (.NET 6+)
int[] nums = { 1, 2, 3, 4, 5, 6, 7 };
var chunks = nums.Chunk(3);
foreach (var chunk in chunks)
{
Console.WriteLine(string.Join(", ", chunk));
}
// Output:
// 1, 2, 3
// 4, 5, 6
// 7
14. OfType
Filters by type, useful for mixed collections.
object[] mixed = { "hello", 42, "world", 100 };
var strings = mixed.OfType<string>();
foreach (var s in strings)
{
Console.WriteLine(s);
}
// Output:
// hello
// world
15. SelectMany
Projects collections within collections and flattens them.
var students = new[]
{
new { Name = "Alice", Subjects = new[] { "Math", "Science" } },
new { Name = "Bob", Subjects = new[] { "English", "History" } }
};
var allSubjects = students.SelectMany(s => s.Subjects);
foreach (var subject in allSubjects)
{
Console.WriteLine(subject);
}
// Output:
// Math
// Science
// English
// History
Complete Example
var people = new[]
{
new { Name = "Alice", Age = 25, Hobbies = new[] { "Reading", "Hiking" } },
new { Name = "Bob", Age = 30, Hobbies = new[] { "Gaming", "Cycling" } },
new { Name = "Charlie", Age = 25, Hobbies = new[] { "Swimming" } }
};
// Select names of people over 20, ordered by name, group by age.
var query = people
.Where(p => p.Age > 20)
.OrderBy(p => p.Name)
.GroupBy(p => p.Age);
foreach (var group in query)
{
Console.WriteLine($"Age: {group.Key}");
foreach (var p in group)
Console.WriteLine($" - {p.Name}");
}
// Use SelectMany to flatten hobbies.
var allHobbies = people.SelectMany(p => p.Hobbies).Distinct();
Console.WriteLine("All hobbies: " + string.Join(", ", allHobbies));
Key Takeaways
- LINQ makes querying data in C# clear and concise.
- You can use Query or Method syntax.
- Mastering methods like Zip, Chunk, OfType, and SelectMany will make your code more powerful and expressive.
- LINQ works with collections, SQL, XML, and more — one consistent approach for all.
Conclusion
Language Integrated Query (LINQ) is more than just syntactic sugar in C# — it’s a robust querying framework that unifies the way developers access and transform data. Whether you're working with in-memory objects, databases, XML, or mixed data sources, LINQ provides a consistent, expressive, and readable way to write queries.
In this article, we explored both the foundational and advanced LINQ methods, including essentials like Where, Select, and GroupBy, as well as powerful operators such as Zip, Chunk, OfType, and SelectMany. Each method serves a unique purpose, helping developers write cleaner, safer, and more maintainable code.