Правильный метод «статического» Random.Next в C #? - PullRequest
25 голосов
/ 15 апреля 2010

Зачем мне создавать экземпляр класса Random, если я хочу создать случайное число от 1 до 100 .... как

Random rand = new Random();
rand.Next(1,100);

Есть ли статическая функция класса Random, которая делает то же самое? как ...

Random.Next(1,100);

Я не хочу создавать экземпляр без необходимости

Ответы [ 11 ]

32 голосов
/ 15 апреля 2010

Лучше всего создать один экземпляр Random и использовать его во всей программе - иначе результаты могут быть не случайными. Такое поведение поощряется тем, что не создается статическая функция.

Вам не нужно беспокоиться о «ненужном создании экземпляра», влияние в лучшем случае незначительно - так работает фреймворк.

26 голосов
/ 15 апреля 2010
//Function to get random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
    lock(syncLock) { // synchronize
        return random.Next(min, max);
    }
}

Скопировано непосредственно из

6 голосов
/ 31 марта 2013

Вы уже получили ответы здесь. Просто повторяя правильное решение :

namespace mySpace
{
    public static class Util
    {
        private static Random rnd = new Random();
        public static int GetRandom()
        {
            return rnd.Next();
        }
    }
}

Так что вы можете позвонить:

var i = Util.GetRandom();

на всем протяжении. Если вам строго необходим настоящий статический метод без сохранения состояния для генерации случайных чисел, вы можете положиться на Guid.

public static class Util
{
    public static int GetRandom()
    {
        return Guid.NewGuid().GetHashCode();
    }
}

Это будет немного медленнее, но может быть гораздо более случайным, чем Random.Next, по крайней мере из моего опыта.

Но не :

new Random(Guid.NewGuid().GetHashCode()).Next();

Создание ненужного объекта замедлит работу, особенно в цикле.

и никогда :

new Random().Next();

Не только медленнее (внутри цикла), но и случайность ... ну, на мой взгляд, не очень хорошо ..

6 голосов
/ 15 апреля 2010

Это не «ненужно», потому что класс Random внутренне хранит некоторые состояния. Он делает это, чтобы убедиться, что если вы наберете .Next() несколько раз очень быстро (за одну и ту же миллисекунду или тик или что-то еще), вы все равно не получите тот же номер.

Конечно, , если , это не проблема, в вашем случае вы всегда можете объединить эти две строки кода в одну:

new Random().Next(1, 100);
5 голосов
/ 15 апреля 2010

С MSDN: случайный класс (система) :

"Генерация случайного числа начинается с начального значения. Если одно и то же начальное число используется многократно, генерируется одна и та же серия чисел. Один из способов получения различных последовательностей состоит в том, чтобы сделать начальное значение зависимым от времени, тем самым создавая другое ряды с каждым новым экземпляром Random. По умолчанию конструктор без параметров класса Random использует системные часы для генерации своего начального значения , в то время как его параметризованный конструктор может принимать значение Int32 на основе числа тиков в текущее время. Однако, поскольку часы имеют конечное разрешение, использование конструктора без параметров для создания различных случайных объектов в последовательной последовательности создает генераторы случайных чисел, которые генерируют идентичные последовательности случайных чисел . Следующий пример иллюстрирует, что два случайных числа объекты, которые создаются в тесной последовательности, генерируют идентичные серии случайных чисел ... "

Википедия объясняет PRNG

3 голосов
/ 31 октября 2015

Лучший способ сделать это - иметь экземпляр ThreadStatic Random:

[ThreadStatic] static Random random;

Random Get() {
 if (random == null) random = new Random(Guid.NewGuid().GetHashCode());
 return random;
}

Это заботится о всем .

  1. Резьба безопасности
  2. Производительность
  3. Не нужно сеять

Это ускользает от меня, почему .NET Framework (и любой другой фреймворк на земле) не использует что-то в этом духе.

3 голосов
/ 15 апреля 2010

Создание нового экземпляра Random и последующий вызов его сразу несколько раз, например ::10000

for (int i = 0; i < 1000; i++)
{
     Random rand = new Random();
     Console.WriteLine(rand.Next(1,100));
}    

Даст вам распределение, взвешенное в направлении нижней границы диапазона.

Делаем так:

Random rand = new Random();
for (int i = 0; i < 1000; i++)
{
     Console.WriteLine(rand.Next(1,100));
}    

Даст вам лучшее распределение.

3 голосов
/ 15 апреля 2010

Почему бы и нет?

Вам необходимо создать экземпляр, поскольку способ генерации случайных чисел заключается в том, что предыдущие ответы влияют на последующие ответы. По умолчанию конструктор new Random() использует текущее системное время для «заполнения» последовательности, но это не обязательно: вы можете передать свой собственный номер, если хотите. В частности:

var rand = new Random(1234);
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));
Console.WriteLine(rand.Next(0, 100));

Каждый раз будет выдавать одну и ту же последовательность «случайного» числа.

Это означает, что классу Random необходимо хранить данные экземпляра (предыдущий ответ или "начальное число") для последующих вызовов.

1 голос
/ 30 января 2012

Генераторы случайных чисел должны поддерживать состояние, чтобы быть «случайным». Генератор случайных чисел создает последовательность, которая генерируется на основе случайного начального числа. Проблема в том, что в компьютере нет ничего случайного. Самая близкая вещь, которую компьютер имеет под рукой, - системные часы; это фактически время, в которое происходит процесс. Таким образом, по умолчанию используется текущий счетчик системных часов. Если ваше приложение достаточно быстрое, тогда многие вычисления случайных чисел могут выполняться под одним и тем же системным тиком. Если генератор случайных чисел вообще не поддерживает состояние, он будет выдавать одно и то же случайное число несколько раз (один и тот же вход дает один и тот же выход). Обычно это не то, что вы хотите.

Я знаю, что он уже ответил, но я просто должен сказать, что я предпочитаю использовать шаблон синглтона в этом случае.

1 голос
/ 15 апреля 2010

Создание недолговечного экземпляра в C # практически бесплатно.Не тратьте свое время на беспокойство по этому поводу.Вероятно, у вас есть лучшие места, чтобы искать перф или увеличение памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...