A New Way to Randomize in .NET 8

We've all used random numbers in C# for various reasons. It has never been difficult to get a random number and use it, we've all probably written something like this:

public int GetRandomNumber(int max)
{
    var random = new Random();
    return random.Next(max);
}

// Or as a single line
var num = new Random().Next(100);

Easy, simple, and short.

.NET 6 gave us a wonderful new property on the Random class: Shared. Random now comes with a static instance and there is no need to new up a Random ever again. The above code becomes this:

public int GetRandomNumber(int max) => Random.Shared.Next(max);

A one liner that arguably does not need to exist. It would be just as easy to not have that function at all and simply call Random.Shared.Next() whenever you need a random number.

That's great! But what if what I really want is a random value from a set list of values? Now we need to get a list or array of values and pick one based on a random number. Let's say you have an enum of Colors:

public enum Color {
    Red, Orange, Yellow, Green, Blue, Indigo, Violet
}

And that you want to pick one at random:

public Color GetRandomColor()
{
    Color[] colors = Enum.GetValues<Colors>();
    return colors[Random.Shared.Next(colors.Length - 1)];
}

Not terrible, but what if we need more than 1? Now it's getting ugly:

public List<Color> GetRandomColors(int count)
{
    List<Color> results = new List<Color>();
    Color[] colors = Enum.GetValues<Colors>();
    int max = colors.Length - 1;
    for (var i = 0; i < count; i++)
    {
        results.Add(colors[Random.Shared.Next(max)]);
    }

    return results;
}

Or even worse, what if we have a list that we need to shuffle?

void ShuffleInPlace<T>(T[] items)
{
    var count = items.Length;
    for (var i = 0; i < count; i++)
    {
        var index = Random.Shared.Next(count);
        var trade = items[index];
        items[index] = items[i];
        items[i] = trade;
    }
}

All of the above functions are clunky and feel like they shouldn't be necessary. Fortunately, with .NET 8 they no longer are! Random got 2 new functions: GetItems() and Shuffle(). The first two functions become one liners:


var color = Random.Shared.GetItems(Enum.GetValues<Colors>(), 1).Single();
var colors = Random.Shared.GetItems(Enum.GetValues<Colors>(), 25).ToList();

And with Shuffle you can randomize an array or a span in place in a single line of code:

var colors = Random.Shared.GetItems(Enum.GetValues<Colors>(), 25);
Random.Shared.Shuffle(colors);

I love these new functions and I'm looking forward to using them. What do you think? Are these useful or bloat? Can you think of another practical use for randomizing a group of objects?

Did you find this article valuable?

Support Ryan Phillips by becoming a sponsor. Any amount is appreciated!