Top 10 Underappreciated LINQ Methods

LINQ (Language Integrated Query) is a powerful feature in .NET that allows developers to query collections in a concise and readable manner. While methods like Where, Select, OrderBy, and GroupBy are widely used and appreciated, there are several other LINQ methods that are often underappreciated but can be incredibly useful.

In this blog post, we'll explore the top 10 underappreciated LINQ methods with examples to help you harness their full potential.

1. Aggregate

The Aggregate method applies an accumulator function over a sequence. This is useful for performing complex calculations or aggregations.

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        var numbers = new[] { 1, 2, 3, 4, 5 };
        var sum = numbers.Aggregate((acc, x) => acc + x);
        Console.WriteLine($"Sum: {sum}");
        var product = numbers.Aggregate((acc, x) => acc * x);
        Console.WriteLine($"Product: {product}");
    }
}

2. Zip

The Zip method merges two sequences by combining their elements pairwise using a specified function.

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        var numbers = new[] { 1, 2, 3 };
        var words = new[] { "one", "two", "three" };
        var zipped = numbers.Zip(words, (n, w) => $"{n} is {w}");
        foreach (var item in zipped)
        {
            Console.WriteLine(item);
        }
    }
}

3. Chunk

The Chunk method splits a sequence into chunks of a specified size.

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        var numbers = Enumerable.Range(1, 10);
        var chunks = numbers.Chunk(3);
        foreach (var chunk in chunks)
        {
            Console.WriteLine(string.Join(", ", chunk));
        }
    }
}

4. TakeWhile and SkipWhile

The TakeWhile method returns elements from a sequence as long as a specified condition is true. The SkipWhile method skips elements as long as the condition is true and then returns the remaining elements.

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        var numbers = new[] { 1, 2, 3, 4, 5, 6 };
        var takeWhileLessThanFour = numbers.TakeWhile(n => n < 4);
        Console.WriteLine("TakeWhile < 4: " + string.Join(", ", takeWhileLessThanFour));
        var skipWhileLessThanFour = numbers.SkipWhile(n => n < 4);
        Console.WriteLine("SkipWhile < 4: " + string.Join(", ", skipWhileLessThanFour));
    }
}

5. DistinctBy

The DistinctBy method returns distinct elements from a sequence based on a specified key selector.

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        var people = new List<Person>
        {
            new Person { Name = "Alice", Age = 30 },
            new Person { Name = "Bob", Age = 40 },
            new Person { Name = "Alice", Age = 35 },
        };
        var distinctNames = people.DistinctBy(p => p.Name);
        foreach (var person in distinctNames)
        {
            Console.WriteLine(person.Name);
        }
    }
    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

6. GroupBy

The GroupBy method groups elements in a sequence based on a specified key selector function.

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        var people = new List<Person>
        {
            new Person { Name = "Alice", Age = 30 },
            new Person { Name = "Bob", Age = 40 },
            new Person { Name = "Charlie", Age = 30 },
        };
        var groupedByAge = people.GroupBy(p => p.Age);
        foreach (var group in groupedByAge)
        {
            Console.WriteLine($"Age: {group.Key}");
            foreach (var person in group)
            {
                Console.WriteLine($" - {person.Name}");
            }
        }
    }
    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

7. ToDictionary

The ToDictionary method creates a Dictionary from a sequence according to specified key selector and element selector functions.

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        var people = new List<Person>
        {
            new Person { Name = "Alice", Age = 30 },
            new Person { Name = "Bob", Age = 40 },
            new Person { Name = "Charlie", Age = 35 },
        };

        var dictionary = people.ToDictionary(p => p.Name, p => p.Age);

        foreach (var kvp in dictionary)
        {
            Console.WriteLine($"{kvp.Key}: {kvp.Value}");
        }
    }

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

8. SelectMany

The SelectMany method projects each element of a sequence to an IEnumerable<T> and flattens the resulting sequences into one sequence.

using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
    static void Main()
    {
        var people = new List<Person>
        {
            new Person { Name = "Alice", Pets = new List<string> { "Cat", "Dog" } },
            new Person { Name = "Bob", Pets = new List<string> { "Fish" } },
        };
        var allPets = people.SelectMany(p => p.Pets);
        foreach (var pet in allPets)
        {
            Console.WriteLine(pet);
        }
    }
    class Person
    {
        public string Name { get; set; }
        public List<string> Pets { get; set; }
    }
}

9. Except

The Except method produces the set difference of two sequences, which means elements that are present in the first sequence but not in the second.

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        var numbers1 = new[] { 1, 2, 3, 4, 5 };
        var numbers2 = new[] { 3, 4, 5, 6, 7 };
        var difference = numbers1.Except(numbers2);
        Console.WriteLine("Difference: " + string.Join(", ", difference));
    }
}

10. Partition

The Partition method (available from .NET 6) returns two sequences: one containing elements that satisfy a specified condition, and one containing elements that do not.

using System;
using System.Linq;
class Program
{
    static void Main()
    {
        var numbers = new[] { 1, 2, 3, 4, 5, 6 };
        var (evens, odds) = numbers.Partition(n => n % 2 == 0);
        Console.WriteLine("Evens: " + string.Join(", ", evens));
        Console.WriteLine("Odds: " + string.Join(", ", odds));
    }
}

Conclusion

LINQ is a powerful tool in the .NET ecosystem, providing a wide range of methods to query and manipulate collections. While some methods are widely known and used, others like Aggregate, Zip, Chunk, DistinctBy, and Partition can offer unique and efficient solutions for various programming scenarios. By understanding and utilizing these underappreciated LINQ methods, you can write more concise, readable, and efficient code.

Next Recommended Reading DeleteAllOnSubmit Method in LINQ to SQL