Loading...

Random Operations in C#

Learn how to use the Random class in C# to generate random numbers, values, and selections using Next, NextDouble, and examples.

In C#, the main class for generating random values is System.Random. It is widely used in scenarios such as game mechanics, simulations, and test data generation. In this article, we will explore generating numbers with Random, defining ranges, shuffling arrays, using seeds, and what to do when cryptographically strong randomness is required.


Basic Usage: Next()

Next() generates a non-negative int. Overloaded versions allow specifying ranges.


var rnd = new Random();

int a = rnd.Next();        // 0..Int32.MaxValue
int b = rnd.Next(10);      // 0..9  (upper bound excluded)
int c = rnd.Next(5, 11);   // 5..10 (lower inclusive, upper exclusive)

Console.WriteLine($"{a}, {b}, {c}");

Floating-Point Values: NextDouble()

NextDouble() generates a number between 0.0 and 1.0 (exclusive). You can scale the range.


var rnd = new Random();

double x = rnd.NextDouble();          // [0.0, 1.0)
double y = 5.0 + rnd.NextDouble() * 3;  // [5.0, 8.0)

Console.WriteLine($"{x}, {y:0.000}");

Filling a Byte Array: NextBytes()

If random bytes are needed (e.g., dummy data), use NextBytes.


var rnd = new Random();
byte[] buffer = new byte[8];
rnd.NextBytes(buffer);

Console.WriteLine(BitConverter.ToString(buffer)); // Example: "3F-91-0C-…"

Reproducibility with Seed

Using the same seed with Random produces the same sequence of numbers. Useful for testing.


var r1 = new Random(12345);
var r2 = new Random(12345);

Console.WriteLine(r1.Next() == r2.Next()); // True

Common Mistake: Creating Random Instances Repeatedly

Creating new Random() in quick succession can produce similar/identical results (time-based seed). Solution: Use a single shared instance or Random.Shared.


// BAD
int BadGeneration()
{
    return new Random().Next(100); // new instance every call
}

// GOOD
var rnd = new Random(); // reuse
int GoodGeneration() => rnd.Next(100);

// .NET 6+: Random.Shared (thread-safe)
int BetterGeneration() => Random.Shared.Next(100);

Examples: Color, Student, Code Generation


var rnd = Random.Shared;

// Random color selection
string[] colors = { "Red", "Blue", "Green", "Yellow", "Purple" };
string chosenColor = colors[rnd.Next(colors.Length)];
Console.WriteLine("Chosen color: " + chosenColor);

// Random student selection
string[] students = { "Alice", "Bob", "Emma", "David", "Sophia" };
string chosenStudent = students[rnd.Next(students.Length)];
Console.WriteLine("Chosen student: " + chosenStudent);

// Random code generation (6 characters)
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var sb = new System.Text.StringBuilder();
for (int i = 0; i < 6; i++)
    sb.Append(chars[rnd.Next(chars.Length)]);
Console.WriteLine("Verification code: " + sb.ToString());

Array Shuffling (Fisher–Yates)

To shuffle elements with equal probability, use the Fisher–Yates algorithm.


var rnd = Random.Shared;
int[] array = { 1, 2, 3, 4, 5 };

for (int i = array.Length - 1; i > 0; i--)
{
    int j = rnd.Next(0, i + 1); // 0..i
    (array[i], array[j]) = (array[j], array[i]);
}

Console.WriteLine(string.Join(", ", array));

Random Pick

Selecting a random item from a collection:


var rnd = Random.Shared;
string[] colors = { "Red", "Blue", "Green", "Yellow" };

string pick = colors[rnd.Next(colors.Length)];
Console.WriteLine("Pick: " + pick);

Simple Random Password (Demo)

Not cryptographically secure; suitable for games/test data. For security, use the method below.


var rnd = Random.Shared;
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
int length = 10;

var sb = new System.Text.StringBuilder(length);
for (int i = 0; i < length; i++)
{
    int idx = rnd.Next(alphabet.Length);
    sb.Append(alphabet[idx]);
}
Console.WriteLine("Password (demo): " + sb.ToString());

Cryptographically Strong Randomness

For security-critical scenarios like password, token, or key generation, do not use Random. Instead, use System.Security.Cryptography.RandomNumberGenerator or the RandomNumber helpers.


using System.Security.Cryptography;

// 0..int.MaxValue (exclusive)
int n1 = RandomNumberGenerator.GetInt32(int.MaxValue);

// Specific range
int n2 = RandomNumberGenerator.GetInt32(100, 201); // 100..200

// Random bytes
byte[] key = new byte[32];
RandomNumberGenerator.Fill(key);

Console.WriteLine($"{n1}, {n2}, {BitConverter.ToString(key)}");

Note on Distribution

Random produces values close to a uniform distribution. For distributions like Normal (Gaussian), transformations (e.g., Box–Muller) or statistical libraries are required.


TL;DR

  • Random.Next, NextDouble, NextBytes → core APIs.
  • Use a single instance or Random.Shared; avoid repeated new Random().
  • Same seed → same number sequence (reproducible tests).
  • Use Fisher–Yates for array shuffling.
  • For security, use RandomNumberGenerator / GetInt32.