Por que a class System.Random não está estática?

Quando você usa a class System.Random , você deve fazer uma instância dela. Por que não é static ? Porque se eu quiser um número random entre 0 e 9, eu posso usar o método estático, System.Random.Next(int, int) :

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

Então, por que a class não é apenas static ?

Você não seria capaz de usar sementes diferentes se fosse estático – a instância Random rastreia esse estado. Por padrão, Random usa a hora atual como semente, mas reutilizar uma semente específica (isto é, new Random(42) ) permite que você repita exatamente a seqüência de números randoms – eles sempre serão os mesmos para a mesma semente. Este aspecto é muito importante em algumas aplicações. Por exemplo, Minecraft.

Random não é thread-safe. É bom ter uma instância de Random por thread, mas você não deve usar uma instância de vários threads simultaneamente. Então você não pode ter apenas uma instância de Random em uma variável estática e usar isso do método estático.

Além disso, torná-lo estático seria remover a oportunidade de dar uma semente específica, como mencionado pela BrokenGlass .

É claro que não seria muito difícil criar methods estáticos que cuidassem da segurança do encadeamento quando você não precisasse especificar uma semente, mas ainda assim deixar os methods da instância para quando você quiser usar uma instância específica. Pessoalmente, considero apropriado tratar “uma fonte de números randoms” como uma dependência a ser injetada quando apropriado.

Eu tenho um artigo que cobre algumas dessas e que você pode achar útil.

Às vezes você quer “algo random” e não se importa como esse valor random é alcançado. Ter um método estático para isso poderia funcionar.

No entanto, às vezes você quer ser capaz de obter repetidamente a mesma seqüência aleatória. Para isso, você usa a sobrecarga do construtor que recebe um valor inicial e, nesse caso, não deseja que nenhum outro código que esteja usando números randoms consuma um dos números da sua sequência. Nesse caso, você definitivamente precisa de uma instância da class

Ter uma sequência ‘aleatória’ repetível é útil em cenários de teste.

Por exemplo, você pode usá-lo no teste de um mecanismo de jogo para garantir que uma AI esteja selecionando destinos ou caminhos corretamente, mesmo que tenha uma avaliação de caminho random.

Aqui está um exemplo muito simplista. Não importa quantas vezes você execute este teste, ele sempre escolherá as mesmas três cartas quando receber o mesmo gerador de números randoms. Isso pode ser útil para garantir que o gerador de números randoms sendo usado seja o fornecido. E, por algum motivo, se um novo gerador de números randoms fosse introduzido sem alterar o teste, o teste falharia.

 [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 _cards = new List { 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 Cards { get { return _cards; } } public Card PickCard() { return Cards[_randomizer.Next(0, Cards.Count - 1)]; } } public class Card { public int Value { get; set; } } 

Muitas vezes, quando se está depurando um programa, o comportamento inadequado em uma etapa pode não apresentar sintomas visíveis até que muitas outras etapas sejam executadas, quando a causa original pode ter sido obscurecida. Nesses casos, pode ser muito útil poder recomeçar do zero um programa que funcionou mal, por exemplo, no passo 1.000.000 e executá-lo nos primeiros 999.990 passos, exatamente como fez na primeira vez, e então fazer uma pausa para permitir que o programador examine seu programa. Estado. Essa debugging não será possível se um programa gerar números realmente “randoms”, mas será, se ele usar um gerador pseudo-random que pode ser recarregado na segunda execução com a mesma semente usada na primeira execução.