LINQ (Language Integrated Query) is a revolutionary feature in C# that transforms how developers work with data. Whether you're just starting with C# or looking to enhance your coding skills, mastering LINQ will significantly improve your productivity and code quality.
What is LINQ in C#?
LINQ integrates querying capabilities directly into the C# language, providing a consistent way to query data from different sources - arrays, collections, databases, XML, and more. Using LINQ in C# eliminates the need to learn multiple query languages for different data formats.
// Basic LINQ query example
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0);
// Result: 2, 4
101 Essential LINQ Operations in C#
Let's explore the most important LINQ operations:
using System;
using System.Linq;
using System.Collections.Generic;
class LinqTutorials
{
static void Main(string[] args)
{
Console.WriteLine("=== LINQ in C# Tutorial: 101 LINQ Operations ===");
// Basic collections setup
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
List<string> fruits = new List<string> { "apple", "banana", "cherry", "date" };
List<int> moreNumbers = new List<int> { 5, 6, 7, 8, 9 };
Console.WriteLine("=== Basic LINQ Filtering with Where ===");
// 1. Basic Where filter
var evenNumbers = numbers.Where(x => x%2==0);
Console.WriteLine("Even numbers :" + string.Join(", ",evenNumbers));
// SQL: SELECT Number FROM Numbers WHERE Number % 2 = 0;
// Result: 2, 4
// 2. Complex Where filter
var evenAndGreaterThan3 = numbers.Where(x => x%2==0 && x > 3);
Console.WriteLine("Even numbers And Greater than 3: " + string.Join(", ", evenAndGreaterThan3));
// SQL: SELECT Number FROM Numbers WHERE Number % 2 = 0 AND Number > 3;
// Result: 4
Console.WriteLine("\n=== LINQ Select Operations in C# ===");
// 3. Simple Select
var same = numbers.Select(n => n);
Console.WriteLine("Same numbers: " + string.Join(", ", same));
// SQL: SELECT Number FROM Numbers;
// Result: 1, 2, 3, 4, 5
// 4. Select with transformation
var doubled = numbers.Select(x => x*2);
Console.WriteLine("Doubled: " + string.Join(", ", doubled));
// SQL: SELECT Number * 2 AS DoubledNumber FROM Numbers;
// Result: 2, 4, 6, 8, 10
// 5. Select with anonymous type
var squares = numbers.Select(x => new{ Number = x , Square =x*x});
Console.WriteLine("Squares: " + string.Join(", ", squares));
// SQL: SELECT Number, Number * Number AS Square FROM Numbers;
// Result: { Number = 1, Square = 1 }, { Number = 2, Square = 4 }, etc.
Console.WriteLine("\n=== Using LINQ OrderBy in C# ===");
// 6. Basic OrderBy
var orderedNumbers = numbers.OrderBy(n => n);
Console.WriteLine("Ordered numbers: " + string.Join(", ", orderedNumbers));
// SQL: SELECT Number FROM Numbers ORDER BY Number ASC;
// Result: 1, 2, 3, 4, 5
// 7. OrderByDescending
var descendingNumbers = numbers.OrderByDescending(n => n);
Console.WriteLine("Descending numbers: " + string.Join(", ", descendingNumbers));
// SQL: SELECT Number FROM Numbers ORDER BY Number DESC;
// Result: 5, 4, 3, 2, 1
// 8. Multiple ordering criteria
var orderedFruits = fruits.OrderBy(x => x.Length).ThenBy(x => x);
Console.WriteLine("Fruits ordered by length then alphabetically: " + string.Join(", ", orderedFruits));
// SQL: SELECT Name FROM Fruits ORDER BY LENGTH(Name) ASC, Name ASC;
// Result: date, apple, banana, cherry
Console.WriteLine("\n=== LINQ GroupBy Tutorial ===");
// 9. GroupBy operation
var groupedByRemainder = numbers.GroupBy(x => x%3);
foreach (var group in groupedByRemainder)
{
Console.WriteLine($"Numbers with remainder {group.Key} when divided by 3: {string.Join(", ", group)}");
}
// SQL: SELECT Number % 3 AS Remainder, Number FROM Numbers GROUP BY Number % 3;
// Result:
// Numbers with remainder 1 when divided by 3: 1, 4
// Numbers with remainder 2 when divided by 3: 2, 5
// Numbers with remainder 0 when divided by 3: 3
Console.WriteLine("\n=== Using LINQ Join in C# ===");
List<Student> students = new List<Student>
{
new Student { ID = 1, Name = "Alice", Age = 21 },
new Student { ID = 2, Name = "Bob", Age = 23 },
new Student { ID = 3, Name = "Charlie", Age = 20 }
};
List<Course> courses = new List<Course>
{
new Course { StudentID = 1, CourseName = "Math" },
new Course { StudentID = 1, CourseName = "Physics" },
new Course { StudentID = 2, CourseName = "Chemistry" },
new Course { StudentID = 3, CourseName = "Biology" }
};
// 10. Inner Join
var studentCourses = students.Join(
courses,
student => student.ID,
course => course.StudentID,
(student,course) => new {
student.Name , course.CourseName
}
);
Console.WriteLine("Student courses (Join):");
foreach (var item in studentCourses)
{
Console.WriteLine($"{item.Name} is taking {item.CourseName}");
}
// SQL: SELECT s.Name, c.CourseName FROM Students s INNER JOIN Courses c ON s.ID = c.StudentID;
// Result:
// Alice is taking Math
// Alice is taking Physics
// Bob is taking Chemistry
// Charlie is taking Biology
Console.WriteLine("\n=== C# LINQ Set Operations ===");
// 11. Union
var union = numbers.Union(moreNumbers);
Console.WriteLine("Union: " + string.Join(", ", union));
// SQL: SELECT Number FROM Numbers UNION SELECT Number FROM MoreNumbers;
// Result: 1, 2, 3, 4, 5, 6, 7, 8, 9
// 12. Intersect
var intersection = numbers.Intersect(moreNumbers);
Console.WriteLine("Intersection: " + string.Join(", ", intersection));
// SQL: SELECT Number FROM Numbers INTERSECT SELECT Number FROM MoreNumbers;
// Result: 5
// 13. Except
var except = numbers.Except(moreNumbers);
Console.WriteLine("Except: " + string.Join(", ", except));
// SQL: SELECT Number FROM Numbers EXCEPT SELECT Number FROM MoreNumbers;
// Result: 1, 2, 3, 4
Console.WriteLine("\n=== LINQ Element Operations Tutorial ===");
// 14. First
var first = numbers.First();
Console.WriteLine("First number: " + first);
// SQL: SELECT TOP 1 Number FROM Numbers;
// Result: 1
// 15. First with condition
var firstEven = numbers.First(n => n%2==0);
Console.WriteLine("First even number: " + firstEven);
// SQL: SELECT TOP 1 Number FROM Numbers WHERE Number % 2 = 0;
// Result: 2
// 16. FirstOrDefault
var firstOver10 = numbers.FirstOrDefault(n => n > 10);
Console.WriteLine("First number > 10 (or default): " + firstOver10);
// SQL: SELECT TOP 1 Number FROM Numbers WHERE Number > 10;
// Result: 0 (default value for int)
// 17. Last
var last = numbers.Last();
Console.WriteLine("Last number: " + last);
// SQL: SELECT TOP 1 Number FROM Numbers ORDER BY Number DESC;
// Result: 5
// 18. Single - throws exception if more than one match
try
{
var singleFive = numbers.Single(n => n == 5);
Console.WriteLine("Single number = 5: " + singleFive);
// SQL: SELECT Number FROM Numbers WHERE Number = 5;
// Result: 5
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
}
// 19. ElementAt
var elementAt = numbers.ElementAt(2);
Console.WriteLine("Element at index 2: " + elementAt);
// SQL equivalent would require ROW_NUMBER() or similar
// Result: 3
Console.WriteLine("\n=== 101 LINQ Examples: Quantifier Operations ===");
// 20. Any
bool hasEven = numbers.Any(n => n % 2 == 0);
Console.WriteLine("Has even numbers: " + hasEven);
// SQL: SELECT CASE WHEN EXISTS (SELECT 1 FROM Numbers WHERE Number % 2 = 0) THEN 1 ELSE 0 END;
// Result: True
// 21. All
bool allPositive = numbers.All(n => n > 0);
Console.WriteLine("All numbers positive: " + allPositive);
// SQL: SELECT CASE WHEN NOT EXISTS (SELECT 1 FROM Numbers WHERE NOT (Number > 0)) THEN 1 ELSE 0 END;
// Result: True
// 22. Contains
bool contains3 = numbers.Contains(3);
Console.WriteLine("Contains 3: " + contains3);
// SQL: SELECT CASE WHEN EXISTS (SELECT 1 FROM Numbers WHERE Number = 3) THEN 1 ELSE 0 END;
// Result: True
Console.WriteLine("\n=== LINQ Partitioning Tutorial ===");
// 23. Take
var firstThree = numbers.Take(3);
Console.WriteLine("First 3 numbers: " + string.Join(", ", firstThree));
// SQL: SELECT TOP 3 Number FROM Numbers;
// Result: 1, 2, 3
// 24. Skip
var skipTwo = numbers.Skip(2);
Console.WriteLine("Skip first 2 numbers: " + string.Join(", ", skipTwo));
// SQL: SELECT Number FROM Numbers ORDER BY (SELECT NULL) OFFSET 2 ROWS;
// Result: 3, 4, 5
// 25. TakeWhile
var takeWhileLessThan4 = numbers.TakeWhile(n => n < 4);
Console.WriteLine("Take while < 4: " + string.Join(", ", takeWhileLessThan4));
// SQL: SELECT Number FROM Numbers WHERE Number < 4;
// Result: 1, 2, 3
// 26. SkipWhile
var skipWhileLessThan4 = numbers.SkipWhile(n => n < 4);
Console.WriteLine("Skip while < 4: " + string.Join(", ", skipWhileLessThan4));
// SQL: SELECT Number FROM Numbers WHERE Number >= 4;
// Result: 4, 5
}
}
class Student
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
class Course
{
public int StudentID { get; set; }
public string CourseName { get; set; }
}
Using LINQ in C#: Key Operators Explained
Filtering with Where
The Where operator filters a collection based on a predicate:
var evenNumbers = numbers.Where(n => n % 2 == 0);
Transforming with Select
The Select operator transforms each element:
var doubled = numbers.Select(n => n * 2);
Sorting with OrderBy
OrderBy sorts elements in ascending order:
var orderedNumbers = numbers.OrderBy(n => n);
Grouping with GroupBy
GroupBy organizes elements into groups based on a key:
var groupedByRemainder = numbers.GroupBy(n => n % 3);
Joining Collections
Join combines elements from two collections:
GroupBy organizes elements into groups based on a key:
var studentCourses = students.Join(courses,
student => student.ID,
course => course.StudentID,
(student, course) => new { student.Name, course.CourseName });
Conclusion
What I like most about LINQ is how it lets me think about what data I need rather than how to get it. The way I can chain operations like Where, Select, and OrderBy together feels natural and makes my intentions clear. When I'm reading code with LINQ, I can quickly understand what it's trying to accomplish.
I'm still learning, but already LINQ has become an essential part of how I write C#. Whether I'm working with simple lists, complex objects, or database queries, having a consistent way to express my data needs is incredibly valuable. I'm excited to keep exploring more LINQ operations and discovering new ways to solve problems with this powerful tool.