Почему class System.Random не статичен?
Когда вы используете class System.Random
, вы должны сделать его экземпляр. Почему это не static
? Поскольку, если я хочу случайное число от 0 до 9, я могу использовать статический метод System.Random.Next(int, int)
:
int ourRandomNumber = Random.Next(0,9);
Так почему же class не просто static
?
- Java Static vs Instance
- Вызывает статические методы через объект «плохая форма»? Зачем?
- Создание экземпляра Generic с переменной, содержащей тип
- Что такое экземпляр Java?
- Как инициализатор экземпляра отличается от конструктора?
- C #: как - одно приложение экземпляра, которое принимает новые параметры?
- Почему я получаю: «Ссылка на объект не установлена на экземпляр объекта». Но не связана ли строка кода?
- Должен ли я использовать это ключевое слово, когда я хочу ссылаться на переменные экземпляра внутри метода?
- Что делает объект jQuery отображаться как массив в инструментах разработчика Chrome?
- Шаблон для ленивого streamобезопасного создания одноэлементов в java
- Swift: создание массива со значением по умолчанию для отдельных экземпляров объекта
- Разница между classами, объектами и экземплярами
- В чем разница между экземпляром и объектом?
Вы не могли бы использовать разные семена, если бы они были статическими – случайный экземпляр отслеживает это состояние. По умолчанию Random использует текущее время в качестве семени, но повторное использование определенного семени (т.е. new Random(42)
) позволяет точно повторять последовательность случайных чисел – они всегда будут одинаковыми для одного и того же семени. Этот аспект очень важен в некоторых приложениях. Например, Minecraft.
Random
не является streamобезопасным. Хорошо иметь один экземпляр Random
в streamе, но вы не должны использовать один экземпляр из нескольких streamов одновременно. Таким образом, вы не можете просто иметь один экземпляр Random
в статической переменной и использовать его из статического метода.
Кроме того, делая его статическим, удалят возможность дать конкретное семя, как упоминалось в BrokenGlass
.
Конечно, было бы не слишком сложно создавать статические методы, которые позаботились о безопасности streamов, когда вам не нужно указывать семя, но при этом оставите методы экземпляра, когда вы хотите использовать конкретный экземпляр. Лично я считаю целесообразным рассматривать «источник случайных чисел» в качестве зависимости, которую нужно вводить, когда это необходимо.
У меня есть статья, которая охватывает некоторые из них и которые вы можете найти полезными.
Иногда вам нужно «что-то случайное», и вам все равно, как это случайное значение будет достигнуто. Наличие статического метода для этого может работать.
Однако иногда вы хотите, чтобы у вас была возможность повторить одну и ту же случайную последовательность. Для этого вы используете перегрузку конструктора, который принимает начальное значение, и в этом случае вы не хотите, чтобы какой-либо другой код использовал случайные числа для использования одного из чисел из вашей последовательности. В этом случае вам определенно нужен экземпляр classа
Наличие повторяемой «случайной» последовательности полезно при тестировании сценариев.
Например, вы можете использовать его при тестировании игрового движка, чтобы гарантировать, что ИИ правильно выбирает цели или пути, даже если он имеет случайную оценку пути.
Вот очень упрощенный пример. Независимо от того, сколько раз вы запускаете этот тест, он всегда будет выбирать одни и те же три карты при использовании одного и того же базового генератора случайных чисел. Это может быть полезно для обеспечения использования используемого генератора случайных чисел. И по какой-то причине, если новый генератор случайных чисел был введен без изменения теста, то тест завершится неудачей.
[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; } }
Часто, когда вы отлаживаете программу, неправильное поведение на одном шаге может не иметь видимых симптомов до тех пор, пока не будет выполнено еще много шагов, и к тому времени исходная причина может быть скрыта. В таких случаях может быть очень полезно иметь возможность перезапускать с нуля программу, которая сработала, например, на этапе 1,000,000, и запустить первые 999990 шагов так же, как и в первый раз, а затем сделать паузу, чтобы позволить программисту изучить его государство. Такая отладка будет невозможна, если программа генерирует действительно «случайные» числа, но будет, если вместо нее будет использоваться псевдослучайный генератор, который можно перезагрузить во втором прогоне с тем же самым семенем, который использовался при первом запуске.