Randomness with the Random class
At some point, you will likely need to achieve randomness in your application. The reasons can be many - maybe you need to sort the items of a list into a random order (shuffling) or maybe you are in the process of creating a game and you want the opponent to move in a random direction. No matter what the reason is, you need some kind of way to obtain a random value from the computer, and fortunately, C# can help us with this.
In most cases, it starts with the Random class, which will allow you to generate one or several random numbers within a specific range. It's even quite simple to use:
Random random = new Random(); Console.WriteLine("A random number: " + random.Next());
We just initialize a new instance of the Random class and then we call the Next() method to get a random number (integer) - very simple stuff!
If you need a number with decimals instead of an integer, you can use the NextDouble() method instead - it will give you a number between 0.0 (included) and 0.99 (anything below 1.0, really):
Random random = new Random(); Console.WriteLine("A random number with decimals: " + random.NextDouble());
A Random range
In most cases, you don't want just any random number - you want it within some kind of range, e.g. between 1 and 100. No worries, the Random class can do that very easily:
Random random = new Random(); Console.WriteLine("A random number between 1 and 100: " + random.Next(1, 101));
I simply change the Next() call to one that includes a minimum and a maximum number. Notice that while the minimum value is inclusive (this number is included in the possible outcome), the maximum value is exclusive (this number is NOT included in the possible outcome), which is why I use 101 instead of 100. If you wanted the number to between 0 and 99, it would instead look like this:
Console.WriteLine("A random number between 0 and 99: " + random.Next(0, 100));
Seeding the Random class
The Random class is always instantiated with a seed, either directly if you supply one, or indirectly by the framework. This seed allows you to basically control the randomness - a specific seed used multiple times will allow you to create the same set of random numbers. This may sound strange, but it can be useful for testing specific scenarios in your application/game.
A seed is supplied to the Random class by using the constructor overload like this:
Random random = new Random(1000);
Let's see what happens if we use this to generate 5 random numbers after eachother:
Random random = new Random(1000); for(int i = 0; i < 5; i++) Console.WriteLine("A random number between 1 and 100: " + random.Next(1, 101));
No matter how many times you run this code, I'm pretty sure that the 5 "random" numbers you get will look like this:
A random number between 1 and 100: 16 A random number between 1 and 100: 24 A random number between 1 and 100: 76 A random number between 1 and 100: 1 A random number between 1 and 100: 70
So as you can see, the random values created by the Random class are not that random after all. Instead, they use the seed value to create pseudo-random values. Therefore, when a seed is not supplied by you, the framework will create one for you. In the original .NET framework, the current time is used, while the more modern .NET core framework will use the thread-static, pseudo-random number generator, to generate a seed. So in other words, unless you need controlled randomness, you can simply stick with the default constructor of the Random class, as used in the first examples.
Use the Random class to generate a random number, but unless you want it to be predictably random, a random seed needs to be used - the framework will take care of this for you, unless you specifically supply a seed through the constructor overload.
Also be aware that instantiating the Random class is somewhat expensive, so don't do this multiple times inside a loop - instead, just instantiate a single Random instance and call the Next() method as many times as you need to.
Lastly, as we already discussed, the Random class is a pseudo-random generator. If you need something that's more secure, e.g. for cryptography and/or random password generation, you can use the RNGCryptoServiceProvider class.