---
title: "6 useful extensions for IEnumerable "
description: "I did already write about some useful extension methods for `Task` and `ValueTask`. Today I want to show you some useful extension methods for `IEnumerable`."
updated: 2023-05-23
tags: ["C#", ".NET"]
canonical: "https://steven-giesel.com/blogPost/1b8eaaef-01a3-4799-9a96-f0d37197d175/6-useful-extensions-for-ienumerable-"
---

# 6 useful extensions for IEnumerable 

I did already write about some useful extension methods for `Task` and `ValueTask`. Today I want to show you some useful extension methods for `IEnumerable`.

## Disclaimer
Those methods are extension methods for `IEnumerable`. Be careful if your underlying type is something like `IQueryable` because we might materialize the query here. 
Instead of `IEnumerable` you could use `IReadOnlyCollection` so you know that you are not dealing with a queryable and your collection at hand is already materialized.

## `IsNullOrEmpty`
Just like `string`, we can introduce a `IsNullOrEmpty` extension method for `IEnumerable`:

```csharp
public static bool IsNullOrEmpty<T>(this IEnumerable<T>? source) => source is null || !source.Any();

var isEmpty = Enumerable.Empty<int>().IsNullOrEmpty(); // true
var isEmpty = new[] { 1, 2, 3 }.IsNullOrEmpty(); // false
var isEmpty = ((IEnumerable<int>)null).IsNullOrEmpty(); // true
```


## Partitioning
Partitioning is a common operation on collections. We can partition a collection into two collections. One collection contains all elements that match a predicate and the other collection contains all elements that do not match the predicate. 

```csharp
public static (IEnumerable<T> True, IEnumerable<T> False) Partition<T>(
        this IEnumerable<T> source,
        Func<T, bool> predicate)
    {
        ArgumentNullException.ThrowIfNull(source);
        ArgumentNullException.ThrowIfNull(predicate);

        var trueItems = new List<T>();
        var falseItems = new List<T>();

        foreach (var item in source)
        {
            if (predicate(item))
                trueItems.Add(item);
            else
                falseItems.Add(item);
        }

        return (trueItems, falseItems);
    }
}
```

The usage would be like this:

```csharp
var (even, odd) = numbers.Partition(n => n % 2 == 0);
Console.WriteLine($"Even numbers: {string.Join(", ", even)}");
Console.WriteLine($"Odd numbers: {string.Join(", ", odd)}");
```

Output:
```no-class
Even numbers: 0, 2, 4
Odd numbers: 1, 3
```

## `Median`
The median is the middle number in a sorted, ascending or descending, list of numbers and can be more descriptive of that data set than the average. **LINQ** itself ships the `Average` extension method but not the `Median` extension method. We can easily add it:

```csharp
public static double Median<T>(this IEnumerable<T> source) where T : IConvertible
{
    ArgumentNullException.ThrowIfNull(source);

    var sortedList = source.Select(x => x.ToDouble(CultureInfo.InvariantCulture)).OrderBy(x => x).ToList();
    var count = sortedList.Count;

    if (count == 0)
    {
        throw new InvalidOperationException("The source sequence is empty.");
    }

    if (count % 2 == 0)
    {
        return (sortedList[count / 2 - 1] + sortedList[count / 2]) / 2;
    }

    return sortedList[count / 2];
}
```

Usage:
```csharp
var median = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }.Median(); // 5
var average = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }.Average(); // 4.333333333333333
```

## `Mode`
The mode is the number that is repeated most often in a set of numbers. We can easily add it:

```csharp
public static IEnumerable<T> Mode<T>(this IEnumerable<T> source)
{
    ArgumentNullException.ThrowIfNull(source);

    var groups = source.GroupBy(x => x);
    var maxCount = groups.Max(g => g.Count());
    return groups.Where(g => g.Count() == maxCount).Select(g => g.Key);
}
```

Usage:
```csharp
var mode = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }.Mode(); // 1
```

If two numbers are repeated the same amount of times, we get both numbers!

## `StandardDeviation`
The standard deviation is a measure of how spread out numbers are.

```csharp
public static double StandardDeviation<T>(this IEnumerable<T> source) where T : IConvertible
{
    ArgumentNullException.ThrowIfNull(source);

    var values = source.Select(x => x.ToDouble(CultureInfo.InvariantCulture)).ToList();
    var count = values.Count;

    if (count == 0)
    {
        throw new InvalidOperationException("The source sequence is empty.");
    }

    var avg = values.Average();
    var sum = values.Sum(d => Math.Pow(d - avg, 2));
    return Math.Sqrt(sum / count);
}
```

Usage:
```csharp
var standardDeviation = new[] { 1, 1, 1, 1, 5, 6, 7, 8, 9 }.StandardDeviation(); // 3.1622776601683795
```

## Shuffle
This method shuffles the elements in a sequence using Fisher-Yates shuffle algorithm.

```csharp
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source)
{
    ArgumentNullException.ThrowIfNull(source);

    var elements = source.ToArray();
    var random = Random.Shared;
    for (var i = elements.Length - 1; i > 0; i--)
    {
        var swapIndex = random.Next(i + 1);
        (elements[i], elements[swapIndex]) = (elements[swapIndex], elements[i]);
    }

    return elements;
}
```

Usage:
```csharp
var numbers = Enumerable.Range(0, 5);
var random = numbers.Shuffle();

// 4, 0, 1, 3, 2
Console.WriteLine(string.Join(", ", random));
```

## Conclusion
Today we saw some useful extension methods for `IEnumerable`. I hope you find them useful. If you have any questions or feedback feel free to leave a comment below.