Generating random numbers is one of those tasks that seems trivial until you need it in production. I've used random integers for testing data, game logic, shuffling lists, and generating unique IDs. And I've also debugged issues caused by misusing the Random class.
Here's how to generate random integers in C# correctly.
using System;
// Install via NuGet: Install-Package System
var random = new Random();
int randomNumber = random.Next(1, 101); // 1 to 100 inclusive
Console.WriteLine(randomNumber);
That's the basic pattern. But there are several overloads, gotchas, and use cases worth understanding.
How Do I Generate a Random Integer?
The Random class has three versions of the Next() method:
var random = new Random();
int any = random.Next(); // Any non-negative int
int upTo100 = random.Next(100); // 0 to 99
int range = random.Next(10, 20); // 10 to 19
Important: The upper bound is exclusive. Next(10, 20) never returns 20 — only 10 through 19.
I trip up on this occasionally when I want inclusive ranges. For 1-100 inclusive, use Next(1, 101).
Why Shouldn't I Create New Random() in a Loop?
This is the most common mistake:
// DON'T DO THIS
for (int i = 0; i < 5; i++)
{
var random = new Random();
Console.WriteLine(random.Next(100));
}
// Output: 47, 47, 47, 47, 47 (same number repeated)
Random is seeded by the current timestamp. If you create multiple instances in quick succession, they get the same seed and produce identical sequences.
Do this instead:
var random = new Random();
for (int i = 0; i < 5; i++)
{
Console.WriteLine(random.Next(100));
}
// Output: 47, 83, 12, 91, 55 (different numbers)
Create one Random instance and reuse it. I keep a static instance in utility classes or inject it via dependency injection in larger applications.
How Do I Generate Random Numbers in a Specific Range?
Use the two-parameter overload:
var random = new Random();
int diceRoll = random.Next(1, 7); // 1 to 6 (simulating a die)
int temperature = random.Next(-10, 40); // -10 to 39 degrees
For inclusive upper bounds, add 1:
int percentage = random.Next(0, 101); // 0 to 100 inclusive
I use this for generating test data — realistic ages, prices, quantities.
Can I Generate Cryptographically Secure Random Numbers?
Not with Random. For security-sensitive scenarios (tokens, passwords, encryption keys), use RandomNumberGenerator:
using System.Security.Cryptography;
byte[] randomBytes = new byte[4];
RandomNumberGenerator.Fill(randomBytes);
int secureRandom = BitConverter.ToInt32(randomBytes, 0);
Or for a random integer in a range:
int secureRandom = RandomNumberGenerator.GetInt32(1, 101); // 1 to 100
Random is predictable if an attacker knows the seed. RandomNumberGenerator uses the operating system's entropy pool — much harder to predict.
I use RandomNumberGenerator for session tokens, API keys, and password reset codes. For everything else, Random is fine.
How Do I Use a Seed for Reproducible Randomness?
Pass a seed to the constructor:
var random = new Random(12345);
Console.WriteLine(random.Next(100)); // Always 33
Console.WriteLine(random.Next(100)); // Always 18
Same seed = same sequence. This is invaluable for testing:
[Test]
public void TestShuffleAlgorithm()
{
var random = new Random(42); // Fixed seed
var list = new[] { 1, 2, 3, 4, 5 };
Shuffle(list, random);
// Same seed produces same shuffle every time
Assert.AreEqual(new[] { 3, 1, 5, 2, 4 }, list);
}
I use seeded random in unit tests to eliminate flakiness. The test runs identically every time, but still exercises randomized logic.
What About Random Numbers in Multi-Threaded Code?
Random is not thread-safe. Sharing an instance across threads causes incorrect results:
// DON'T DO THIS
var random = new Random();
Parallel.For(0, 100, i =>
{
Console.WriteLine(random.Next(100)); // Corrupted state
});
Use ThreadLocal<Random>:
var random = new ThreadLocal<Random>(() => new Random());
Parallel.For(0, 100, i =>
{
Console.WriteLine(random.Value.Next(100)); // Safe
});
Each thread gets its own Random instance. I use this pattern in parallel processing pipelines where each worker needs random data.
Can I Generate Random Bytes?
Yes, for byte arrays:
var random = new Random();
byte[] buffer = new byte[10];
random.NextBytes(buffer);
Console.WriteLine(BitConverter.ToString(buffer));
// Output: 9C-4F-12-A7-3E-8B-... (random bytes)
I use this for generating random binary data in file I/O tests.
How Do I Generate Random Doubles or Floats?
NextDouble() returns a value between 0.0 and 1.0:
var random = new Random();
double value = random.NextDouble(); // 0.0 to 1.0 (exclusive)
Scale it to any range:
double price = random.NextDouble() * 100; // 0.0 to 100.0
double temperature = random.NextDouble() * 50 - 10; // -10.0 to 40.0
For more control over distributions (Gaussian, Poisson, etc.), use MathNet.Numerics:
using MathNet.Numerics.Distributions;
var gaussian = new Normal(mean: 100, stdDev: 15);
double iqScore = gaussian.Sample(); // Normally distributed around 100
I use this for generating realistic test data — heights, weights, reaction times.
How Does Random Apply to PDF Generation?
When building dynamic reports, I sometimes need randomized sample data for demos or testing. Here's how I combine Random with IronPDF:
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var random = new Random();
var html = "<h1>Sample Report</h1><table>";
for (int i = 0; i < 10; i++)
{
int quantity = random.Next(1, 100);
decimal price = (decimal)(random.NextDouble() * 1000);
html += $@"
<tr>
<td>Item {i + 1}</td>
<td>{quantity}</td>
<td>${price:F2}</td>
</tr>";
}
html += "</table>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("SampleReport.pdf");
This generates a PDF with randomized data for demos. IronPDF's Chromium engine renders the HTML perfectly, and the random data looks realistic.
I built a demo system for a sales team where they could generate sample invoices with randomized line items. The full guide to random numbers in C# covers more advanced scenarios.
What's the Difference Between Random and RandomNumberGenerator?
| Feature | Random | RandomNumberGenerator |
|---|---|---|
| Speed | Fast | Slower |
| Security | Predictable | Cryptographically secure |
| Thread-safe | No | Yes |
| Use cases | Games, testing, sampling | Tokens, keys, passwords |
| Distribution | Uniform | Uniform |
Use Random for general purposes. Use RandomNumberGenerator when security matters.
How Do I Shuffle a List Randomly?
Fisher-Yates shuffle:
void Shuffle<T>(T[] array, Random random)
{
for (int i = array.Length - 1; i > 0; i--)
{
int j = random.Next(i + 1);
(array[i], array[j]) = (array[j], array[i]); // Swap
}
}
var cards = new[] { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };
var random = new Random();
Shuffle(cards, random);
I use this for randomizing test cases, shuffling quiz questions, or implementing card games.
Can I Weight Random Choices?
For non-uniform distributions, calculate cumulative weights:
string[] items = { "Common", "Uncommon", "Rare" };
double[] weights = { 0.7, 0.25, 0.05 }; // 70%, 25%, 5%
string WeightedChoice(string[] items, double[] weights, Random random)
{
double totalWeight = weights.Sum();
double randomValue = random.NextDouble() * totalWeight;
double cumulative = 0;
for (int i = 0; i < items.Length; i++)
{
cumulative += weights[i];
if (randomValue < cumulative)
return items[i];
}
return items[^1];
}
var random = new Random();
for (int i = 0; i < 10; i++)
{
Console.WriteLine(WeightedChoice(items, weights, random));
}
I built a loot drop system for a game prototype using this pattern. Common items drop frequently, rare items rarely.
Quick Reference
| Method | Output |
|---|---|
Next() |
Any non-negative int |
Next(100) |
0 to 99 |
Next(10, 20) |
10 to 19 |
NextDouble() |
0.0 to 1.0 |
NextBytes(buffer) |
Random bytes |
RandomNumberGenerator.GetInt32(1, 101) |
Secure 1 to 100 |
The key principles: reuse your Random instance, understand that upper bounds are exclusive, and use RandomNumberGenerator for anything security-related.
Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.
Top comments (0)