2

私は最近、メンバー@dtbによって編集されたここでの質問に答えました。

C#で0〜9の一意の乱数で配列を埋める

質問にはRandom()の使用が含まれ、メンバーはこの一般的な落とし穴を回避するために私の回答を編集したと述べました(彼が言ったように)

私の元のコードは、次のように、この問題に対して単独で脆弱ではありませんでした。

public void DoStuff()
{
    var rand = new Random();
    while() {} //Inner loop that uses 'rand'
}

答えは編集されました。意図はループ内で関数を呼び出すことであるように見えたため、コードが脆弱になりますが、基本的に次のように変更されました。

public void DoStuff(Random R)
{
    while() {} //Inner loop that uses 'rand'
}

私の当面の考えは、ランダムインスタンスをスタックのさらに上に維持する負担を押し上げただけであり、問​​題のプログラマーがそれがどのように実装されているかを理解していない場合でも、この落とし穴に陥ります。

私の質問は、.NetのRandom()がJavascriptの場合と同じように実装されていないのはなぜですか?1つの静的なグローバルRandom()(たとえば、AppDomainごとに?)ですか?当然のことながら、シードを制御する必要がある非常にまれなケースでは、現在の時刻をシードとして使用する、より明示的なオーバーロード/メソッドを提供することもできます。

確かに、これはこの非常に一般的な落とし穴を回避するでしょう。誰かが.Netアプローチの利点について私に教えてもらえますか?

編集:シードを制御することが重要であることを理解していますが、デフォルトでこれを強制することは奇妙な選択のようです。誰かがシードを制御したい場合、彼らは自分が何をしているのかを知っている可能性があります。

乾杯。

4

2 に答える 2

5

これにより、複数の乱数発生源を制御できるためです。各インスタンスに同じシードを設定することで、必要に応じて同じシーケンスを生成できます。また、他のアクションが数値の流れに影響を与えたくない場合もあります。

ゲームを考えてみてください。すべてのランダムはシード番号から生成されるため、プレイヤーの入力とランダム シードを保存すると、ゲーム全体を最初から最後まで再現できます。しかし、プレイ中にパーティクルなどのランダムなものを生成したり、その他の無関係だがランダムなものを生成したりする場合、それらも保存したくありません。最も簡単な方法は、2 つの random を宣言することです。1 つは重要なもの用で、もう 1 つはそれ以外のもの用です。しかし、これはほんの一例です。

したがって、必要に応じてランダム シーケンスを宣言する自由があり、このように使用する場合はトリックを使用する必要はありません。

于 2012-05-22T09:56:10.063 に答える
5

.NET ソリューションは、単一のグローバル ジェネレーターを使用するソリューションよりも柔軟です。これにより、アプリケーションの各部分で、反復可能な疑似乱数の独立したシーケンスを作成して使用できるようになります。これは、デバッグ目的に不可欠です。疑似乱数に依存するコードのデバッグは、最初から楽しいものではありません。コードの異なる部分から同じジェネレーターにアクセスすると、アクセスできなくなります。

同時に、 の共有インスタンスが必要な場合はRandom、数行のコードで簡単にアプリケーションで使用できるようにすることができます。

// !!! This is not thread safe!!!
static class RandomHelper {
    private static readonly Random rnd = new Random();
    public static Random Instance {get { return rnd; } }
}
于 2012-05-22T09:56:20.843 に答える