フッターコンテンツにスキップ
Iron Academy Logo
C#を学ぶ
C#を学ぶ

その他のカテゴリー

C#でのランダム数生成

Tim Corey
10m 05s

C#でランダムな数値を生成することは、ワンライナーであるべきだと考えられますが、多くの場合そうです。 しかし、言語はランダムな値を生成するための複数の方法を提供しており、スレッドセーフ性、再現可能性、使用ケースを考慮に入れるとその違いが重要になります。 誤ったアプローチを選ぶと、マルチスレッドのコードで微妙なバグを引き起こしたり、報告された欠陥を再現不可能にすることがあります。

彼のビデオ"C#でランダムな数を生成する"で、Tim Coreyは古典的なRandom.Sharedを現代のデフォルトとして紹介します。 各アプローチとその背後にある理由を扱いますので、推測することなく正しいものを選ぶことができます。 なぜそんなに単純に聞こえるものに複数の道があるのか不思議に思ったことがあるならば、この記事はそれを解き明かします。

デモの設定

[0:11 - 0:59] TimはVisual Studio 2026(現在プレビュー中)で.NET 10を使って実行しているコンソールアプリケーション内で作業しています。彼は、ここで示されたすべてが.NET 9およびVisual Studio 2022に同様に適用されることを指摘していますので、既にインストールされているツールを使用してフォローすることができます。

デモレイアウトは、各反復で2つのランダムな値を並べて印刷するforループです。 平行して実行される2つの出力を持つことで、両方のジェネレーターが独立して動作するか、同じ結果をもたらすかを観察するのが簡単になりますが、シード値が関与するとその区別が重要になります。

クラシックなRandomクラス

[0:59 - 3:28] C#でランダム整数を生成する元の方法は、Randomクラスのインスタンスを作成することです:

Random rng1 = new Random();
Random rng2 = new Random();
Random rng1 = new Random();
Random rng2 = new Random();

各インスタンスは独自の内部状態を維持します。 どちらを呼び出しても1から100の間の整数を生成します。Timは新人が間違いやすい点を強調します:最小値は含まれますが、最大値は含まれません。1から100までの値が欲しい場合は、100ではありません。

int output1 = rng1.Next(1, 101);
int output2 = rng2.Next(1, 101);
int output1 = rng1.Next(1, 101);
int output2 = rng2.Next(1, 101);

アプリケーションを実行すると、両方のインスタンスが異なるシーケンスを生成することが確認されます。 その結果は直感的に感じられますが、両方のインスタンスが同じ開始点を共有すると何が起こるかは別の話を語ります。

このアプローチに関する重要な警告:個々のRandomインスタンスはスレッドセーフではありません。 アプリケーションが並列処理を行い、複数のスレッドが同じインスタンスにアクセスする場合、内部状態が破損し、0や繰り返しの値を生成する可能性があります。 安全な方法はスレッドごとに1つのインスタンスを作成することです。 この制約が、後に言語がより良い代替案を導入した理由の一つです。

シード値と再現可能なシーケンス

[3:28 - 6:00] Timは次に、両方のコンストラクターに明示的なシードを渡します:

Random rng1 = new Random(25);
Random rng2 = new Random(25);
Random rng1 = new Random(25);
Random rng2 = new Random(25);

出力が劇的に変わります。 両方のジェネレーターが今や同一のシーケンスを生成します:79, 16, 25, 90, 50, 41など。 シードを知らない場合、数値は依然として個々には予測不可能ですが、同じ開始値を考慮に入れると、進行は決定的です。

なぜ誰かこれを望むのでしょうか? Timは実践的な例を示します。 あるゲームがセッション全体でランダムなイベントを生成すると想像してください。 プレイヤーがバグを報告しますが、結果がランダム化されているため再現が不可能に感じられます。 そのセッションで使用されたシードをゲームがログに記録する場合、開発者は同じ値を使用して新しいRandomインスタンスを初期化することで、決定の正確な連鎖を再現できます。 同様の論理が、一貫した出力を必要とし、ランダム化された動作に対して信頼性のあるアサーションを書く必要がある単体テストのシナリオにも適用されます。

シードされたインスタンスは、制御されたランダム性を提供します:一見予測不可能に見えるが、要求に応じてリプレイできるシーケンス。 この機能により、シードを受け取る古典的なRandomコンストラクタは、シンプルなAPIが現在存在するにもかかわらず、廃止されていません。

Random.Shared: モダンなデフォルト

[7:36 - 9:01] .NET 6から、推奨されるアプローチRandom.Sharedです:

int output1 = Random.Shared.Next(1, 101);
int output2 = Random.Shared.Next(1, 101);
int output1 = Random.Shared.Next(1, 101);
int output2 = Random.Shared.Next(1, 101);

インスタンス化は不要です。 Randomクラスの他のメソッド)ことで、オブジェクトのライフタイムや並行性を気にせずに値を受け取ることができます。

Timはその証明のためにデモを2回実行します。 最初の実行は94と91から始まります。 2番目は42と70で開始します。シード付きインスタンスとは異なり、Random.Sharedはプロセスが開始されるたびに異なる開始状態から取得します。 シードを設定することはできません。つまり、このAPIを介して再現可能なシーケンスを生成することはできません。 それがトレードオフです:決定的なリプレイを放棄する代わりに、シンプルさと安全性。

Random.Sharedはダブルを生成し、バイト配列を埋め、コレクションをシャッフルするためのメソッドを公開しています。 迅速なランダム値を必要とするアプリケーションコードの大部分にとって、この単一の静的プロパティは、独自のインスタンスを管理するボイラープレートを置き換えます。

正しいアプローチの選択

[9:01 - 9:30] Timは簡潔な決定フレームワークで締めくくります。 日常的なランダム性(値の選択、リストのシャッフル、ランダムな要素の選択)には、Random.Sharedが適しています。 セットアップ不要で、同時実行を処理し、スレッド全体で正しく動作します。

デバッグ、テスト、またはシミュレーションの再生のために再現可能な出力シリーズが必要な場合は、既知のシードで専用のRandomインスタンスを作成します。 これらのインスタンスをスレッド間で共有することは安全ではないことを忘れないでください。

そして、セキュリティに関わる何か(トークン、キー、パスワードの塩分)には、どちらのアプローチも適していません。 Timは視聴者にSystem.Security.Cryptographyの暗号ライブラリを参照するよう指示します。これにより、ランダムであるだけでなく、予測に強い値が生成されます。

締めくくり:シンプルなAPI、意味深い違い

[9:30 - 9:50] このトピックを誤解しやすいのは、どのアプローチでもそれほど多くのコードがかからないからです。 1行だけでランダムな数を生成することができます。 複雑さは構文ではなく、各メソッドが提供する保証、つまりスレッドセーフ性、再現可能性、または暗号強度を理解することにあります。

結論

[9:50 - 10:05] 要約すると:Random.Sharedはゼロセットアップと組み込みのスレッドセーフでほとんどのニーズをカバーします。 シード付きRandomインスタンスは、デバッグまたはテストで必要な特定のシーケンスを再現できます。 暗号生成は予測可能性が脆弱性であり、機能ではないセキュリティに敏感なコードに属します。

次回C#でランダムな数を求めるとき、その決定は1つの質問にかかっています:このシーケンスを後で再生する必要がありますか? 答えがノーである場合、Random.Sharedがすべて必要です。

例のヒント:101を渡す必要があります。 このオフバイワン境界はシードされたインスタンスにも適用されます。

彼のYouTubeチャンネルで完全なビデオを視聴し、C#の基礎に関するさらなる洞察を得てください。

Hero Worlddot related to C#でのランダム数生成
Hero Affiliate related to C#でのランダム数生成

好きなことを共有することで収入を増やす

.NET、C#、Java、Python、またはNode.jsを使用する開発者向けのコンテンツを作成しますか?あなたの専門知識を副収入に変えましょう!

アイアンサポートチーム

私たちは週5日、24時間オンラインで対応しています。
チャット
メール
電話してね