LINQ in C# Tutorial for Beginners: 101 C# LINQ Operations

LINQ in C# Tutorial for Beginners: 101 C# LINQ Operations

LINQ in C#

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.