c# 乱数 小数 - なぜSystem.Randomクラスは静的ではないのですか?



2 Answers

Randomはスレッドセーフではありません。 スレッドごとに1つのインスタンスを持つことは問題ありませんが、同時に複数のスレッドから1つのインスタンスを使用すべきではありません。 したがって、静的変数に1つのインスタンスRandom持つだけで、静的メソッドからそのインスタンスを使用することはできません。

また、それを静的にすると、 BrokenGlassように、特定のシードを与える機会がBrokenGlassます。

もちろん、シードを指定する必要はない 、特定のインスタンスを使用するときにインスタンスメソッドを残しておくと、スレッドの安全性を考慮した静的メソッドを作成するのは難しくありません。 個人的には、「乱数の発生源」を適切な場所に注入する依存関係として扱うことが適切であるとわかります。

私は、 これのいくつかをカバーし、あなたが有用であるかもしれない記事を持っています。

c# 乱数 配列

System.Randomクラスを使用する場合は、そのインスタンスを作成する必要があります。 なぜそれはstaticではないのですか? 0から9までの乱数が必要な場合は、静的メソッド System.Random.Next(int, int)使用できます。

int ourRandomNumber = Random.Next(0,9);

では、なぜクラスはstaticはありませんか?




反復可能な「ランダム」シーケンスを持つことは、シナリオのテストに役立ちます。

たとえば、ゲームエンジンをテストする際にAIを使用して、AIがランダムなパス評価を持っていても、ターゲットまたはパスを正しく選択していることを確認できます。

ここでは非常に単純な例があります。 このテストを何度実行しても、同じ基本乱数ジェネレータが与えられた場合、常に同じ3枚のカードが選択されます。 これは、使用されている乱数ジェネレータが供給されていることを確認するのに便利です。 また、何らかの理由で新しい乱数ジェネレータがテストを変更せずに導入された場合、テストは失敗します。

[TestMethod]
public void TestRandomPicking()
{
    Random random = new Random(1);
    Deck deck = new Deck(random);


    Assert.AreEqual(3, deck.PickCard().Value);
    Assert.AreEqual(1, deck.PickCard().Value);
    Assert.AreEqual(5, deck.PickCard().Value);

}

public class Deck
{
    public Deck()
    {
        _randomizer = new Random();
    }

    public Deck(Random randomizer)
    {
        _randomizer = randomizer; 
    }

    Random _randomizer;

    private List<Card> _cards = new List<Card>
                                    {
                                        new Card {Value = 1},
                                        new Card {Value = 2},
                                        new Card {Value = 3},
                                        new Card {Value = 4},
                                        new Card {Value = 5},
                                        new Card {Value = 6},
                                        new Card {Value = 7},
                                        new Card {Value = 8},
                                        new Card {Value = 9},
                                        new Card {Value = 10}
                                    };

    private List<Card> Cards { get { return _cards; } }

    public Card PickCard()
    {
        return Cards[_randomizer.Next(0, Cards.Count - 1)];
    }
}

public class Card
{
    public int Value { get; set; }
}



Related