Skip to main content

.NET C#/VB
42 LINQ Functions Explained

C#

// AZUL CODING ---------------------------------------
// .NET C#/VB - 42 LINQ Functions Explained
// https://youtu.be/pu4kws7_Jr0


class Program
{
    // .NET 8+ syntax
    static readonly Person[] People =
    [
        new() { Name = "John", Age = 30, Email = "john@example.com" },
        new() { Name = "Jane", Age = 25, Email = "jane@example.com" },
        new() { Name = "Bob", Age = 40, Email = "bob@example.info" },
        new() { Name = "Alice", Age = 35, Email = "alice@example.info" },
        new() { Name = "Eve", Age = 60, Email = "eve@example.net" },
        new() { Name = "Charlie", Age = 18, Email = "charlie@example.net" }
    ];

    static void Output<T>(T p)
    {
        Console.WriteLine(p?.ToString());
    }

    static void Output<T>(IEnumerable<T> items)
    {
        Console.WriteLine($"[{string.Join(", ", items)}]");
    }

    static void Output<T>(IOrderedEnumerable<T> items)
    {
        Console.WriteLine($"[{string.Join(", ", items)}]");
    }
    
    static void Main(string[] args)
    {
        // Query and method syntax
        {
            List<int> numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];

            IEnumerable<int> filterQuerySyntax =
                from num in numbers
                where num is < 3 or > 7
                select num;

            Console.WriteLine(string.Join(", ", filterQuerySyntax));


            IEnumerable<int> filterMethodSyntax = numbers.Where(x => x is < 3 or > 7);

            Console.WriteLine(string.Join(", ", filterMethodSyntax));
        }

        // Where(), First(), FirstOrDefault(), Last() and LastOrDefault()
        {
            Output(People.Where(x => x.Age > 30));
            Output(People.Where(x => x.Name == "Bob"));
            Output(People.Where(x => x.Name == "Bob").First());
            Output(People.Where(x => x.Name == "Bob").FirstOrDefault(defaultValue: new Person()));
            Output(People.Where(x => x.Name == "Bob").Last());
            Output(People.Where(x => x.Name == "Bob").LastOrDefault(defaultValue: new Person()));
        }
        
        // OfType()
        {
            object[] things = [1, "string", 2, 5, "test"];
            Output(things.OfType<string>());
        }

        // Select() and SelectMany()
        {
            Output(People.Select(x => x.Name));
            Output(People.Select(x => x.Age));

            string[] words = ["the quick brown fox", "jumps over", "the lazy dog"];
            Output(words.SelectMany(x => x.Split(" ")));
        }

        // Cast()
        {
            object[] words = ["the quick brown fox", "jumps over", "the lazy dog"];
            Output(words.Cast<string>().SelectMany(x => x.Split(" ")));
        }

        // Enumerable.Repeat() and Enumerable.Range()
        {
            Output(string.Join("", Enumerable.Repeat("-", 10)));

            Output(Enumerable.Range(1, 10));
            Output(Enumerable.Range(1, 10).Where(x => x % 2 == 0));
        }

        // OrderBy() and OrderByDescending()
        {
            Output(People.OrderBy(x => x.Age));
            Output(People.OrderByDescending(x => x.Age));
        }

        // ThenBy(), ThenByDescending() and Reverse()
        {
            Output(People.OrderBy(x => x.Name.Length).ThenBy(x => x.Age));
            Output(People.OrderBy(x => x.Name.Length).ThenByDescending(x => x.Age));
            Output(People.OrderBy(x => x.Name.Length).ThenByDescending(x => x.Age).Reverse());
        }

        // GroupBy()
        {
            var grouping = People.GroupBy(x => x.Email.Split('.').Last());
            foreach (var group in grouping)
                Output($".{group.Key} -> [{string.Join(", ", group)}]");
        }

        // Join() and GroupJoin()
        {
            Pet[] pets =
            [
                new() { Name = "Pip", Owner = People[0] },
                new() { Name = "Ziggy", Owner = People[1] },
                new() { Name = "Luna", Owner = People[2] },
                new() { Name = "Willow", Owner = People[2] },
                new() { Name = "Coco", Owner = People[3] },
                new() { Name = "Bella", Owner = People[3] }
            ];

            Output(People.Join(pets, person => person, pet => pet.Owner, (person, pet) =>
                new { OwnerName = person.Name, PetName = pet.Name }));

            Output(People.GroupJoin(pets, person => person, pet => pet.Owner, (person, pets) =>
                new { OwnerName = person.Name, PetNames = string.Join(", ", pets.Select(pet => pet.Name)) }));
        }

        // All(), Any() and Count()
        {
            Output(People.All(x => x.Age >= 18));
            Output(People.All(x => x.Age >= 65));
            Output(People.Any(x => x.Age >= 65));
            Output(People.Any(x => x.Age >= 50));
            Output(People.Count(x => x.Age >= 50));
        }

        // SequenceEqual()
        {
            Output(People.SequenceEqual(People.Where(x => x.Age >= 18)));
            Output(People.SequenceEqual(People.Where(x => x.Age >= 50)));
        }

        // Skip(), SkipLast(), SkipWhile(), Take(), TakeLast() and TakeWhile()
        {
            var numbers = Enumerable.Range(1, 10);

            Output(numbers.Skip(2));
            Output(numbers.SkipLast(2));
            Output(numbers.SkipWhile(x => x < 4));

            Output(numbers.Take(2));
            Output(numbers.TakeLast(2));
            Output(numbers.TakeWhile(x => x < 4));
        }

        // Chunk()
        {
            var numbers = Enumerable.Range(1, 10);
            
            foreach (var chunk in numbers.Chunk(3))
                Output($"[{string.Join(", ", chunk)}]");
        }

        // Min() and Max()
        {
            var numbers = Enumerable.Range(1, 10);

            Output(numbers.Min());
            Output(numbers.Max());
            Output(People.Min(x => x.Age));
            Output(People.Max(x => x.Age));
        }

        // Average() and Sum()
        {
            var numbers = Enumerable.Range(1, 10);

            Output(numbers.Average());
            Output(People.Average(x => x.Age));

            Output(numbers.Sum());
            Output(People.Sum(x => x.Age));
        }

        // Distinct() and DistinctBy()
        {
            string[] words = ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"];

            Output(words.Distinct());
            Output(words.DistinctBy(x => x.Length));
        }

        // Except() and ExceptBy()
        {
            string[] words = ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"];
            string[] excluded = ["the", "over"];

            Output(words.Except(excluded));
            
            excluded = ["Jane", "Bob"];
            Output(People.ExceptBy(excluded, x => x.Name));
        }

        // Intersect() and Union()
        {
            string[] words = ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy"];
            string[] words2 = ["the", "over", "dog"];

            Output(words.Intersect(words2));
            Output(words.Union(words2));
        }

        // IntersectBy() and UnionBy()
        {
            IEnumerable<Person> people2 = 
            [
                new() { Name = "Steve", Age = 30, Email = "steve@example.com" },
                new() { Name = "Charles", Age = 18, Email = "charlie@example.net" }
            ];

            Output(People.IntersectBy(people2.Select(x => x.Email), (x) => x.Email));
            Output(People.UnionBy(people2, x => x.Email));
        }
    }
}

class Person
{
    public string Name { get; set; } = "";
    public int Age { get; set; } = 0;
    public string Email { get; set; } = "";

    public override string ToString() => $"{Name} ({Age}): {Email}";
}

class Pet
{
    public string Name { get; set; } = "";
    public Person? Owner { get; set; }

    public override string ToString() => Name;
}

Enjoying this tutorial?


VB.NET

' AZUL CODING ---------------------------------------
' .NET C#/VB - 42 LINQ Functions Explained
' https://youtu.be/pu4kws7_Jr0


Module Program
    Private ReadOnly People As Person() = {
        New Person With {.Name = "John", .Age = 30, .Email = "john@example.com"},
        New Person With {.Name = "Jane", .Age = 25, .Email = "jane@example.com"},
        New Person With {.Name = "Bob", .Age = 40, .Email = "bob@example.info"},
        New Person With {.Name = "Alice", .Age = 35, .Email = "alice@example.info"},
        New Person With {.Name = "Eve", .Age = 60, .Email = "eve@example.net"},
        New Person With {.Name = "Charlie", .Age = 18, .Email = "charlie@example.net"}
    }

    Private Sub Output(Of T)(p As T)
        Console.WriteLine(p?.ToString())
    End Sub

    Private Sub Output(Of T)(items As IEnumerable(Of T))
        Console.WriteLine($"[{String.Join(", ", items)}]")
    End Sub

    Private Sub Output(Of T)(items As IOrderedEnumerable(Of T))
        Console.WriteLine($"[{String.Join(", ", items)}]")
    End Sub

    Sub Main(args As String())

        ' Query and method syntax
        Dim numbers As New List(Of Integer) From {5, 4, 1, 3, 9, 8, 6, 7, 2, 0}

        Dim filterQuerySyntax = From num In numbers
                                Where num < 3 OrElse num > 7
                                Select num

        Console.WriteLine(String.Join(", ", filterQuerySyntax))

        Dim filterMethodSyntax = numbers.Where(Function(x) x < 3 OrElse x > 7)

        Console.WriteLine(String.Join(", ", filterMethodSyntax))


        ' Where(), First(), FirstOrDefault(), Last() and LastOrDefault()
        Output(People.Where(Function(x) x.Age > 30))
        Output(People.Where(Function(x) x.Name = "Bob"))
        Output(People.Where(Function(x) x.Name = "Bob").First())
        Output(People.Where(Function(x) x.Name = "Bob").FirstOrDefault(New Person()))
        Output(People.Where(Function(x) x.Name = "Bob").Last())
        Output(People.Where(Function(x) x.Name = "Bob").LastOrDefault(New Person()))


        ' OfType()
        Dim things As Object() = {1, "string", 2, 5, "test"}
        Output(things.OfType(Of String)())


        ' Select() and SelectMany()
        Output(People.Select(Function(x) x.Name))
        Output(People.Select(Function(x) x.Age))

        Dim words As String() = {"the quick brown fox", "jumps over", "the lazy dog"}
        Output(words.SelectMany(Function(x) x.Split(" ")))


        ' Cast()
        Dim wordsObj As Object() = {"the quick brown fox", "jumps over", "the lazy dog"}
        Output(wordsObj.Cast(Of String)().SelectMany(Function(x) x.Split(" ")))


        ' Enumerable.Repeat() and Enumerable.Range()
        Output(String.Join("", Enumerable.Repeat("-", 10)))

        Output(Enumerable.Range(1, 10))
        Output(Enumerable.Range(1, 10).Where(Function(x) x Mod 2 = 0))


        ' OrderBy() and OrderByDescending()
        Output(People.OrderBy(Function(x) x.Age))
        Output(People.OrderByDescending(Function(x) x.Age))


        ' ThenBy(), ThenByDescending() and Reverse()
        Output(People.OrderBy(Function(x) x.Name.Length).ThenBy(Function(x) x.Age))
        Output(People.OrderBy(Function(x) x.Name.Length).ThenByDescending(Function(x) x.Age))
        Output(People.OrderBy(Function(x) x.Name.Length).ThenByDescending(Function(x) x.Age).Reverse())


        ' GroupBy()
        Dim grouping = People.GroupBy(Function(x) x.Email.Split("."c).Last())
        For Each group In grouping
            Output($".{group.Key} -> [{String.Join(", ", group)}]")
        Next


        ' Join() and GroupJoin()
        Dim pets As Pet() = {
            New Pet With {.Name = "Pip", .Owner = People(0)},
            New Pet With {.Name = "Ziggy", .Owner = People(1)},
            New Pet With {.Name = "Luna", .Owner = People(2)},
            New Pet With {.Name = "Willow", .Owner = People(2)},
            New Pet With {.Name = "Coco", .Owner = People(3)},
            New Pet With {.Name = "Bella", .Owner = People(3)}
        }

        Output(People.Join(pets, Function(person) person, Function(pet) pet.Owner, Function(person, pet) New With {
            .OwnerName = person.Name,
            .PetName = pet.Name
        }))

        Output(People.GroupJoin(pets, Function(person) person, Function(pet) pet.Owner, Function(person, petList) New With {
            .OwnerName = person.Name,
            .PetNames = String.Join(", ", petList.Select(Function(pet) pet.Name))
        }))


        ' All(), Any() and Count()
        Output(People.All(Function(x) x.Age >= 18))
        Output(People.All(Function(x) x.Age >= 65))
        Output(People.Any(Function(x) x.Age >= 65))
        Output(People.Any(Function(x) x.Age >= 50))
        Output(People.Count(Function(x) x.Age >= 50))


        ' SequenceEqual()
        Output(People.SequenceEqual(People.Where(Function(x) x.Age >= 18)))
        Output(People.SequenceEqual(People.Where(Function(x) x.Age >= 50)))


        ' Skip(), SkipLast(), SkipWhile(), Take(), TakeLast() and TakeWhile()
        Dim nums = Enumerable.Range(1, 10)

        Output(nums.Skip(2))
        Output(nums.SkipLast(2))
        Output(nums.SkipWhile(Function(x) x < 4))

        Output(nums.Take(2))
        Output(nums.TakeLast(2))
        Output(nums.TakeWhile(Function(x) x < 4))


        ' Chunk()
        Dim chunkNums = Enumerable.Range(1, 10)
        For Each chunk In chunkNums.Chunk(3)
            Output($"[{String.Join(", ", chunk)}]")
        Next


        ' Min() and Max()
        Dim minMaxNums = Enumerable.Range(1, 10)

        Output(minMaxNums.Min())
        Output(minMaxNums.Max())
        Output(People.Min(Function(x) x.Age))
        Output(People.Max(Function(x) x.Age))


        ' Average() and Sum()
        Dim avgSumNums = Enumerable.Range(1, 10)

        Output(avgSumNums.Average())
        Output(People.Average(Function(x) x.Age))

        Output(avgSumNums.Sum())
        Output(People.Sum(Function(x) x.Age))


        ' Distinct() and DistinctBy()
        Dim distinctWords As String() = {"the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"}

        Output(distinctWords.Distinct())
        Output(distinctWords.DistinctBy(Function(x) x.Length))


        ' Except() and ExceptBy()
        Dim exceptWords As String() = {"the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"}
        Dim excluded As String() = {"the", "over"}

        Output(exceptWords.Except(excluded))

        excluded = {"Jane", "Bob"}
        Output(People.ExceptBy(excluded, Function(x) x.Name))


        ' Intersect() and Union()
        Dim intersectWords1 As String() = {"the", "quick", "brown", "fox", "jumps", "over", "the", "lazy"}
        Dim intersectWords2 As String() = {"the", "over", "dog"}

        Output(intersectWords1.Intersect(intersectWords2))
        Output(intersectWords1.Union(intersectWords2))


        ' IntersectBy() and UnionBy()
        Dim people2 As IEnumerable(Of Person) = {
            New Person With {.Name = "Steve", .Age = 30, .Email = "steve@example.com"},
            New Person With {.Name = "Charles", .Age = 18, .Email = "charlie@example.net"}
        }

        Output(People.IntersectBy(people2.Select(Function(x) x.Email), Function(x) x.Email))
        Output(People.UnionBy(people2, Function(x) x.Email))

    End Sub
End Module

Public Class Person
    Public Property Name As String = ""
    Public Property Age As Integer = 0
    Public Property Email As String = ""

    Public Overrides Function ToString() As String
        Return $"{Name} ({Age}): {Email}"
    End Function
End Class

Public Class Pet
    Public Property Name As String = ""
    Public Property Owner As Person

    Public Overrides Function ToString() As String
        Return Name
    End Function
End Class