C# Randomの使い方を完全解説|乱数生成・範囲指定・重複しない方法まで
はじめに
C#で乱数を扱うときによく使うのがRandomクラスです。サイコロの目を出す、配列からランダムに要素を選ぶ、ゲーム内の出現率を決める、抽選処理を行うなど、さまざまな場面で利用されます。
一方で、Randomは使い方を誤ると「同じ値ばかり出る」「重複しない乱数が作れない」「パスワード生成に使ってしまう」といった問題が起こりやすい機能でもあります。
この記事では、C#のRandomの基本的な使い方から、範囲指定、重複しない乱数、配列やリストからのランダム取得、実践的なサンプル、RandomNumberGeneratorとの違いまで、初心者にもわかりやすく解説します。
1. C#のRandomとは?乱数生成の基本を理解する
1-1. Randomクラスでできること
C#のRandomクラスは、疑似乱数を生成するためのクラスです。System名前空間に含まれており、整数、小数、バイト配列などのランダムな値を作成できます。
代表的なメソッドは次のとおりです。
C#Random random = new Random();
int number = random.Next();
double value = random.NextDouble();
byte[] bytes = new byte[10];
random.NextBytes(bytes);
Next()は整数、NextDouble()は0.0以上1.0未満の小数、NextBytes()はバイト配列にランダムな値を入れるために使います。
1-2. 乱数が使われる代表的な場面
Randomは、主に次のような場面で使われます。
ゲーム開発では、敵の出現位置、ダメージ量、アイテムのドロップ率などをランダムに決めるために使われます。業務アプリでは、抽選、サンプルデータ作成、ランダムな並び替えなどに利用できます。
また、学習用のプログラムでも、サイコロ、じゃんけん、クイズの出題順など、ランダム性を持たせたい処理によく登場します。
1-3. Randomと完全なランダムの違い
C#のRandomが生成する値は、厳密には完全なランダムではなく「疑似乱数」です。疑似乱数とは、決まった計算式に基づいてランダムに見える数値を生成する仕組みです。
そのため、同じseed値を指定すると、同じ順番で乱数が生成されます。
C#Random random = new Random(123);
Console.WriteLine(random.Next(1, 100));
Console.WriteLine(random.Next(1, 100));
Console.WriteLine(random.Next(1, 100));
このコードは、実行するたびに同じ結果になります。これはバグではなく、再現性のある乱数を作れるというRandomの特徴です。
1-4. Randomを使う前に知っておきたい注意点
Randomを使うときは、次の点に注意が必要です。
まず、Randomはセキュリティ用途には向いていません。パスワード、認証トークン、暗号鍵などを作る場合は、RandomではなくRandomNumberGeneratorを使います。
また、ループの中で毎回new Random()を作成すると、同じような乱数が連続して出る原因になります。基本的にはRandomインスタンスを1回作成し、それを使い回すのが正しい使い方です。
2. C# Randomの基本的な使い方
2-1. Randomインスタンスの作成方法
Randomを使うには、まずインスタンスを作成します。
C#Random random = new Random();
これで、現在時刻などをもとに初期化された乱数生成器が作られます。
クラス内で使い回す場合は、次のようにフィールドとして定義することもあります。
C#class Program
{
private static readonly Random random = new Random();
static void Main()
{
int number = random.Next(1, 101);
Console.WriteLine(number);
}
}
このように1つのRandomを使い回すことで、同じ乱数が連続して出る問題を避けやすくなります。
2-2. Next()で整数の乱数を生成する
整数の乱数を生成するにはNext()を使います。
C#Random random = new Random();
int number = random.Next();
Console.WriteLine(number);
引数なしのNext()は、0以上の整数をランダムに返します。
上限を指定したい場合は、次のように書きます。
C#int number = random.Next(10);
Console.WriteLine(number);
この場合、生成される値は0以上10未満、つまり0〜9です。
2-3. NextDouble()で小数の乱数を生成する
小数の乱数を生成するにはNextDouble()を使います。
C#Random random = new Random();
double value = random.NextDouble();
Console.WriteLine(value);
NextDouble()は、0.0以上1.0未満のdouble型の値を返します。
たとえば、0.0〜100.0未満の小数を作りたい場合は、次のようにします。
C#double value = random.NextDouble() * 100;
Console.WriteLine(value);
2-4. NextBytes()でバイト配列に乱数を入れる
NextBytes()を使うと、バイト配列にランダムな値を入れられます。
C#Random random = new Random();
byte[] bytes = new byte[10];
random.NextBytes(bytes);
foreach (byte b in bytes)
{
Console.WriteLine(b);
}
byteは0〜255の値を持つ型です。NextBytes()は、配列の各要素にランダムなバイト値を設定します。
ただし、暗号やセキュリティ用途でランダムなバイト列が必要な場合は、Random.NextBytes()ではなくRandomNumberGenerator.GetBytes()を使うべきです。
2-5. Random.Sharedを使う方法
C#では、.NET 6以降でRandom.Sharedを使えます。
C#int number = Random.Shared.Next(1, 101);
Console.WriteLine(number);
Random.Sharedは共有インスタンスを使って乱数を生成できる便利な機能です。毎回new Random()を作成する必要がなく、簡潔に書けます。
C#double value = Random.Shared.NextDouble();
Console.WriteLine(value);
簡単なアプリやマルチスレッド環境では、Random.Sharedを検討するとよいでしょう。
3. C# Randomで範囲を指定して乱数を生成する方法
3-1. 0以上指定値未満の乱数を生成する
0以上、指定した値未満の乱数を生成するには、Next(maxValue)を使います。
C#Random random = new Random();
int number = random.Next(10);
Console.WriteLine(number);
この場合、生成される値は0〜9です。10は含まれません。
3-2. 最小値と最大値を指定して乱数を生成する
最小値と最大値を指定するには、Next(minValue, maxValue)を使います。
C#Random random = new Random();
int number = random.Next(5, 15);
Console.WriteLine(number);
この場合、生成される値は5以上15未満、つまり5〜14です。
3-3. Next(minValue, maxValue)の最大値は含まれない
Random.Next(minValue, maxValue)で特に注意したいのは、最大値が含まれないことです。
C#int number = random.Next(1, 10);
このコードで生成される値は1〜9です。10は出ません。
1〜10の乱数を作りたい場合は、次のように最大値に11を指定します。
C#int number = random.Next(1, 11);
C#のRandomでは、上限値は「未満」と考えるのが重要です。
3-4. 1〜100など任意の範囲で乱数を作る例
1〜100の乱数を作る例は次のとおりです。
C#Random random = new Random();
int number = random.Next(1, 101);
Console.WriteLine(number);
100を含めたい場合は、上限に101を指定します。
サイコロのように1〜6の値を作る場合は、次のように書きます。
C#int dice = random.Next(1, 7);
Console.WriteLine(dice);
3-5. 小数の範囲を指定して乱数を生成する方法
NextDouble()は0.0以上1.0未満の値を返します。任意の範囲の小数を作るには、計算で範囲を調整します。
たとえば、10.0以上20.0未満の小数を作る場合は次のようにします。
C#Random random = new Random();
double min = 10.0;
double max = 20.0;
double value = min + random.NextDouble() * (max - min);
Console.WriteLine(value);
この考え方を使えば、任意の小数範囲で乱数を生成できます。
4. C# Randomでよくある失敗と対処法
4-1. 同じ乱数が連続して出る原因
Randomで同じ乱数が連続して出る原因として多いのが、短時間に何度もnew Random()を作成しているケースです。
C#for (int i = 0; i < 5; i++)
{
Random random = new Random();
Console.WriteLine(random.Next(1, 100));
}
このようなコードでは、同じような値が出やすくなることがあります。特に古い実装や短時間で連続実行する処理では注意が必要です。
4-2. ループ内でRandomをnewしてはいけない理由
Randomは、インスタンスを作成したときの初期値に基づいて乱数列を生成します。ループ内で毎回作成すると、乱数生成器の初期化が繰り返され、期待したランダム性が得られないことがあります。
悪い例は次のとおりです。
C#for (int i = 0; i < 10; i++)
{
Random random = new Random();
Console.WriteLine(random.Next(1, 101));
}
良い例は、Randomをループの外で作る方法です。
C#Random random = new Random();
for (int i = 0; i < 10; i++)
{
Console.WriteLine(random.Next(1, 101));
}
Randomは基本的に使い回すと覚えておきましょう。
4-3. seed値を指定したときの挙動
Randomにはseed値を指定できます。
C#Random random = new Random(100);
Console.WriteLine(random.Next(1, 101));
Console.WriteLine(random.Next(1, 101));
Console.WriteLine(random.Next(1, 101));
seed値を指定すると、同じseedからは同じ順番の乱数が生成されます。
つまり、次のコードを何度実行しても、同じ結果になります。
C#Random random1 = new Random(100);
Random random2 = new Random(100);
Console.WriteLine(random1.Next(1, 101));
Console.WriteLine(random2.Next(1, 101));
これは、テストやシミュレーションで結果を再現したいときに便利です。
4-4. 毎回異なる乱数にする方法
毎回異なる乱数にしたい場合は、通常どおり引数なしでRandomを作成します。
C#Random random = new Random();
int number = random.Next(1, 101);
Console.WriteLine(number);
または、.NET 6以降であればRandom.Sharedを使うのも簡単です。
C#int number = Random.Shared.Next(1, 101);
Console.WriteLine(number);
ただし、同じ処理の中で何度も乱数を生成する場合は、インスタンスを使い回すことが大切です。
4-5. 再現性のある乱数を作る方法
テストやデバッグでは、毎回同じ乱数列を生成したいことがあります。その場合はseed値を固定します。
C#Random random = new Random(12345);
for (int i = 0; i < 5; i++)
{
Console.WriteLine(random.Next(1, 101));
}
このコードは、実行するたびに同じ順番で乱数を出力します。
ゲームのリプレイ機能、シミュレーションの検証、単体テストなどでは、seedを固定した乱数が役立ちます。
5. C# Randomで重複しない乱数を生成する方法
5-1. ListとContainsを使って重複を避ける方法
重複しない乱数を作るもっともわかりやすい方法は、生成済みの値をListに保存し、Containsで確認する方法です。
C#Random random = new Random();
List<int> numbers = new List<int>();
while (numbers.Count < 5)
{
int number = random.Next(1, 11);
if (!numbers.Contains(number))
{
numbers.Add(number);
}
}
foreach (int number in numbers)
{
Console.WriteLine(number);
}
このコードでは、1〜10の中から重複なしで5個の乱数を取得します。
ただし、List.Contains()は要素数が増えると検索に時間がかかるため、大量のデータにはあまり向いていません。
5-2. HashSetを使って効率よく重複しない乱数を作る方法
重複チェックを効率よく行いたい場合は、HashSetを使います。
C#Random random = new Random();
HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < 5)
{
int number = random.Next(1, 11);
numbers.Add(number);
}
foreach (int number in numbers)
{
Console.WriteLine(number);
}
HashSetは重複する値を自動的に追加しないため、重複なし乱数の生成に向いています。
Add()は、すでに同じ値がある場合は追加されません。そのため、明示的にContains()を書く必要がありません。
5-3. 指定範囲の数値をシャッフルして取得する方法
指定範囲の中から重複なしでランダムに取り出す場合は、最初に数値一覧を作り、それをシャッフルする方法もあります。
C#Random random = new Random();
List<int> numbers = Enumerable.Range(1, 10).ToList();
for (int i = numbers.Count - 1; i > 0; i--)
{
int j = random.Next(i + 1);
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
List<int> result = numbers.Take(5).ToList();
foreach (int number in result)
{
Console.WriteLine(number);
}
この方法では、1〜10の数値をランダムに並び替え、その先頭から5個取得しています。大量に重複なしの値を取り出す場合に使いやすい方法です。
5-4. 重複なしでランダムに配列から要素を取り出す方法
配列から重複なしで複数の要素を取り出す場合も、シャッフルしてから必要な件数を取得する方法が便利です。
C#Random random = new Random();
string[] fruits = { "Apple", "Banana", "Orange", "Grape", "Peach" };
List<string> shuffled = fruits.OrderBy(x => random.Next()).ToList();
List<string> selected = shuffled.Take(3).ToList();
foreach (string fruit in selected)
{
Console.WriteLine(fruit);
}
ただし、OrderBy(x => random.Next())は簡単に書けますが、厳密なシャッフルや大量データではFisher-Yatesシャッフルを使う方が適しています。
5-5. 重複なし乱数で注意すべき範囲と個数の関係
重複なし乱数を作るときは、指定範囲より多い個数を取得しようとしないように注意が必要です。
たとえば、1〜10の範囲から重複なしで11個の数値を取得することはできません。
C#int min = 1;
int max = 10;
int count = 11;
if (count > max - min + 1)
{
Console.WriteLine("指定範囲より多い個数は取得できません。");
}
重複なし乱数を作る場合は、必ず「範囲内の個数」と「取得したい個数」の関係を確認しましょう。
6. 配列・リストからランダムに要素を取得する方法
6-1. 配列からランダムに1件取得する
配列からランダムに1件取得するには、配列のインデックスを乱数で作ります。
C#Random random = new Random();
string[] colors = { "Red", "Blue", "Green", "Yellow" };
int index = random.Next(colors.Length);
string selected = colors[index];
Console.WriteLine(selected);
random.Next(colors.Length)は、0以上colors.Length未満の整数を返します。配列のインデックスは0から始まるため、この書き方で安全にランダム取得できます。
6-2. Listからランダムに1件取得する
Listからランダムに1件取得する場合も考え方は同じです。
C#Random random = new Random();
List<string> names = new List<string>
{
"田中",
"佐藤",
"鈴木",
"高橋"
};
int index = random.Next(names.Count);
string selected = names[index];
Console.WriteLine(selected);
ListではCountを使って要素数を取得します。
6-3. 複数件をランダムに取得する
複数件をランダムに取得したい場合は、シャッフルしてからTake()で取得する方法が簡単です。
C#Random random = new Random();
List<string> names = new List<string>
{
"田中",
"佐藤",
"鈴木",
"高橋",
"伊藤"
};
List<string> selected = names
.OrderBy(x => random.Next())
.Take(3)
.ToList();
foreach (string name in selected)
{
Console.WriteLine(name);
}
この方法では、重複なしで3件取得できます。
6-4. 要素をランダムに並び替える
要素をランダムに並び替えるには、Fisher-Yatesシャッフルを使う方法が定番です。
C#Random random = new Random();
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
for (int i = numbers.Count - 1; i > 0; i--)
{
int j = random.Next(i + 1);
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
foreach (int number in numbers)
{
Console.WriteLine(number);
}
後ろから順番にランダムな位置と入れ替えることで、リスト全体をランダムに並び替えられます。
6-5. ゲームや抽選処理で使えるサンプルコード
次は、参加者リストからランダムに当選者を1人選ぶサンプルです。
C#Random random = new Random();
List<string> participants = new List<string>
{
"Alice",
"Bob",
"Charlie",
"Diana"
};
int index = random.Next(participants.Count);
string winner = participants[index];
Console.WriteLine($"当選者は {winner} さんです。");
重複なしで複数人の当選者を選ぶ場合は、シャッフルしてから取得します。
C#Random random = new Random();
List<string> participants = new List<string>
{
"Alice",
"Bob",
"Charlie",
"Diana",
"Eve"
};
List<string> winners = participants
.OrderBy(x => random.Next())
.Take(2)
.ToList();
foreach (string winner in winners)
{
Console.WriteLine($"当選者: {winner}");
}
7. C# Randomの実践的なサンプルコード
7-1. サイコロの目をランダムに出す
サイコロの目は1〜6なので、Next(1, 7)を使います。
C#Random random = new Random();
int dice = random.Next(1, 7);
Console.WriteLine($"サイコロの目: {dice}");
上限の7は含まれないため、結果は1〜6になります。
7-2. ランダムな文字列を生成する
ランダムな文字列を作るには、使用する文字一覧からランダムに文字を選びます。
C#Random random = new Random();
string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int length = 10;
char[] result = new char[length];
for (int i = 0; i < length; i++)
{
int index = random.Next(chars.Length);
result[i] = chars[index];
}
string randomString = new string(result);
Console.WriteLine(randomString);
このコードでは、英数字から10文字のランダムな文字列を生成します。
7-3. ランダムなパスワードを生成する
学習用としてRandomでパスワード風の文字列を作ることはできます。
C#Random random = new Random();
string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%";
int length = 12;
char[] password = new char[length];
for (int i = 0; i < length; i++)
{
password[i] = chars[random.Next(chars.Length)];
}
Console.WriteLine(new string(password));
ただし、実際のパスワード生成にRandomを使うのは避けてください。セキュリティ用途では、後述するRandomNumberGeneratorを使う必要があります。
7-4. 確率を指定して処理を分岐する
確率を指定して処理を分岐したい場合は、NextDouble()を使うと便利です。
C#Random random = new Random();
double probability = 0.3;
if (random.NextDouble() < probability)
{
Console.WriteLine("30%の確率で成功しました。");
}
else
{
Console.WriteLine("失敗しました。");
}
NextDouble()は0.0以上1.0未満の値を返すため、0.3未満なら30%の確率になります。
7-5. ランダムな日付を生成する
指定した期間内でランダムな日付を作るには、開始日から終了日までの日数を求め、その範囲で乱数を作ります。
C#Random random = new Random();
DateTime start = new DateTime(2024, 1, 1);
DateTime end = new DateTime(2024, 12, 31);
int range = (end - start).Days;
DateTime randomDate = start.AddDays(random.Next(range + 1));
Console.WriteLine(randomDate.ToString("yyyy/MM/dd"));
range + 1にすることで、終了日も含めた範囲からランダムに日付を生成できます。
8. RandomとRandomNumberGeneratorの違い
8-1. Randomが向いている用途
Randomは、一般的なランダム処理に向いています。
たとえば、ゲーム内の演出、サイコロ、抽選、ランダムな並び替え、テストデータ作成などです。
C#int dice = Random.Shared.Next(1, 7);
このような用途では、Randomで十分なケースが多いです。
8-2. RandomNumberGeneratorが必要な用途
RandomNumberGeneratorは、暗号学的に安全な乱数を生成するためのクラスです。予測されにくい乱数が必要な場合に使います。
代表的な用途は次のとおりです。
パスワード生成、認証トークン生成、セッションID生成、APIキー生成、暗号鍵生成などです。
これらの用途では、RandomではなくRandomNumberGeneratorを使うべきです。
8-3. パスワードやトークン生成にRandomを使ってはいけない理由
Randomは疑似乱数であり、暗号学的な安全性を目的としていません。seedや出力パターンが推測されると、生成される値を予測される可能性があります。
そのため、次のようなコードを実際のパスワード生成に使うのは避けるべきです。
C#Random random = new Random();
int token = random.Next(100000, 999999);
ワンタイムパスワード、認証コード、セキュリティトークンなど、第三者に推測されると困る値にはRandomNumberGeneratorを使いましょう。
8-4. 暗号学的に安全な乱数を生成する方法
暗号学的に安全な整数を生成するには、RandomNumberGenerator.GetInt32()が便利です。
C#using System.Security.Cryptography;
int number = RandomNumberGenerator.GetInt32(1, 101);
Console.WriteLine(number);
このコードでは、1〜100の範囲で安全な乱数を生成できます。
ランダムなバイト列を生成する場合は、次のようにします。
C#using System.Security.Cryptography;
byte[] bytes = RandomNumberGenerator.GetBytes(32);
Console.WriteLine(Convert.ToBase64String(bytes));
トークンや秘密情報を生成する場合は、このような暗号学的に安全な乱数を使います。
8-5. 用途別の使い分け早見表
用途ごとの使い分けは次のように考えるとわかりやすいです。
| 用途 | 推奨 |
|---|---|
| サイコロ | Random |
| ゲーム内のランダム演出 | Random |
| 抽選処理 | Random |
| テストデータ作成 | Random |
| 再現性のあるシミュレーション | seed付きRandom |
| パスワード生成 | RandomNumberGenerator |
| 認証トークン生成 | RandomNumberGenerator |
| APIキー生成 | RandomNumberGenerator |
| 暗号鍵生成 | RandomNumberGenerator |
通常のランダム処理にはRandom、セキュリティが関係する処理にはRandomNumberGeneratorを使うと覚えておきましょう。
9. C# Randomを安全・効率的に使うベストプラクティス
9-1. Randomインスタンスは使い回す
Randomは、基本的に1つのインスタンスを使い回します。
C#private static readonly Random random = new Random();
メソッドを呼び出すたびにnew Random()を作成するのではなく、フィールドや共有インスタンスとして保持するのが一般的です。
C#int number = random.Next(1, 101);
これにより、同じ値が連続しやすくなる問題や、不要なインスタンス生成を避けられます。
9-2. マルチスレッド環境ではRandom.Sharedを検討する
複数のスレッドから乱数を使う場合は、Random.Sharedを検討できます。
C#int number = Random.Shared.Next(1, 101);
Random.Sharedを使えば、共有インスタンスを簡単に利用できます。シンプルなコードで乱数を扱えるため、現在のC#では便利な選択肢です。
9-3. 範囲指定では上限値が含まれない点に注意する
Random.Next()の範囲指定では、上限値が含まれません。
C#int number = random.Next(1, 10);
このコードで出る値は1〜9です。
1〜10を出したい場合は、次のようにします。
C#int number = random.Next(1, 11);
範囲指定のミスは非常に多いため、上限は「未満」と覚えておきましょう。
9-4. 重複なし乱数は用途に応じて実装を選ぶ
重複なし乱数を作る方法はいくつかあります。
少数の値を取得するだけなら、HashSetを使う方法が簡単です。
C#HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < 5)
{
numbers.Add(Random.Shared.Next(1, 11));
}
範囲内の値を大量に取得する場合は、範囲のリストを作成してシャッフルする方法が向いています。
C#List<int> numbers = Enumerable.Range(1, 10).ToList();
用途やデータ量に応じて、実装方法を選びましょう。
9-5. セキュリティ用途ではRandomNumberGeneratorを使う
パスワード、トークン、認証コードなど、セキュリティに関係する値を作る場合は、必ずRandomNumberGeneratorを使います。
C#using System.Security.Cryptography;
int code = RandomNumberGenerator.GetInt32(100000, 1000000);
Console.WriteLine(code);
Randomは便利ですが、セキュリティ用途には適していません。用途に応じた使い分けが重要です。
10. C# Randomに関するよくある質問
10-1. C#で1から10までの乱数を作るには?
1から10までの乱数を作るには、Next(1, 11)を使います。
C#Random random = new Random();
int number = random.Next(1, 11);
Console.WriteLine(number);
Next()の第2引数は含まれないため、10まで出したい場合は11を指定します。
10-2. Randomで同じ値ばかり出るのはなぜ?
短時間に何度もnew Random()を作成している可能性があります。
悪い例は次のとおりです。
C#for (int i = 0; i < 5; i++)
{
Random random = new Random();
Console.WriteLine(random.Next(1, 10));
}
Randomはループの外で作成して使い回しましょう。
C#Random random = new Random();
for (int i = 0; i < 5; i++)
{
Console.WriteLine(random.Next(1, 10));
}
10-3. Randomのseedとは何?
seedとは、乱数生成の初期値です。同じseedを指定すると、同じ順番で乱数が生成されます。
C#Random random = new Random(123);
seedを固定すると結果を再現できるため、テストやシミュレーションに便利です。
10-4. Random.Sharedとnew Random()はどちらを使うべき?
簡単な処理や共有インスタンスで十分な場合は、Random.Sharedが便利です。
C#int number = Random.Shared.Next(1, 101);
一方で、seedを指定して再現性のある乱数を作りたい場合は、new Random(seed)を使います。
C#Random random = new Random(123);
用途に応じて使い分けるのがよいでしょう。
10-5. C#で重複しないランダムな数字を作るには?
少数の重複なし乱数なら、HashSetを使う方法が簡単です。
C#HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < 5)
{
numbers.Add(Random.Shared.Next(1, 11));
}
foreach (int number in numbers)
{
Console.WriteLine(number);
}
1〜10から5個の重複しない乱数を取得できます。
10-6. Randomはゲーム開発に使っても問題ない?
通常のゲーム開発であれば、Randomは問題なく使えます。敵の出現、ダメージ計算、アイテムドロップ、ランダムイベントなどに利用できます。
ただし、オンラインゲームの不正対策や、予測されると困る重要な処理では、より慎重な設計が必要です。セキュリティが関係する値にはRandomNumberGeneratorを使いましょう。
10-7. パスワード生成にRandomを使ってもよい?
実際のパスワード生成にRandomを使うのはおすすめできません。Randomは暗号学的に安全な乱数ではないため、推測されるリスクがあります。
パスワードやトークンを生成する場合は、RandomNumberGeneratorを使います。
C#using System.Security.Cryptography;
byte[] bytes = RandomNumberGenerator.GetBytes(32);
string token = Convert.ToBase64String(bytes);
Console.WriteLine(token);
セキュリティ用途では、必ず暗号学的に安全な乱数生成を選びましょう。
まとめ
C#で乱数を生成するには、Randomクラスを使います。整数の乱数にはNext()、小数の乱数にはNextDouble()、バイト配列にはNextBytes()を使います。
範囲指定では、Next(minValue, maxValue)の最大値が含まれない点に注意が必要です。たとえば、1〜10の乱数を作る場合はNext(1, 11)と書きます。
また、Randomはループ内で毎回newせず、インスタンスを使い回すのが基本です。.NET 6以降であれば、Random.Sharedを使う方法も便利です。
重複しない乱数を作る場合は、少数ならHashSet、範囲内から大量に取得するならシャッフルを使う方法が向いています。
一方で、Randomはセキュリティ用途には適していません。パスワード、トークン、認証コードなどを生成する場合は、RandomNumberGeneratorを使いましょう。
RandomとRandomNumberGeneratorを正しく使い分けることで、安全で効率的な乱数処理を実装できます。

