Generating a secure random range of number in .NET

At the time of writing, this post is talking about .NET 8. If you are reading this on a newer version, check its documentation and changelog.

If you spent some time writing .NET, you have probably been bitten by the fact that Random is not thread-safe. Well, I'm part of today's lucky 10000!

Some friends and I have a Discord server that we daily use to talk to each other. At some point, one of us had the brilliant idea of writing a bot that would roll a die and mute someone for some time if you got 6. We all found it to be a funny trick and a cool reason to write small useless software1.

We soon noticed that the bot was giving 4 to everyone at the same time. Funnily enough, my friend Júnio saw it from miles away even before reviewing the code: "You are sharing a Random instance between threads, aren't you?". Well, I was... Here is the fix:

[<RequireQualifiedAccess>]
module Random =
open System.Security.Cryptography

  let range fromInclusive toInclusive =
    RandomNumberGenerator.GetInt32(fromInclusive, toInclusive + 1)

Random.range 1 6 // happy secure random number!
  1. Which is the best kind of software, by the way.