.NET: Random.Random будет работать по-другому внутри статического метода - PullRequest
1 голос
/ 29 апреля 2010

У меня проблемы со следующим кодом, который находится внутри статического метода нестатического класса.

int iRand;
int rand;

rand = new Random((int)DateTime.Now.Ticks);
iRand = rand.Next(50000);

Номер iRand, а такжес некоторыми другими значениями, вставляются в новую строку таблицы Access MDB через OLEDB.Номер iRand вставляется в поле, являющееся частью первичного ключа, и попытка вставки вызывает следующее исключение, даже если номер iRand должен быть случайным:

System.Data.OleDb.OleDbException: The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship.  Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again.

Может ли тот факт, чтостатический метод заставляет число iRand оставаться тем же, по какой-то причине?

Ответы [ 5 ]

5 голосов
/ 29 апреля 2010

Вы не должны использовать случайные числа для первичных ключей! Во-первых, да, есть вероятность столкновения, в вашем случае n / 50000, где n - количество ранее созданных чисел. (Спасибо, Гуффа) Во-вторых, почему бы не использовать последовательные значения? сначала начинаются с 1, 2, 3 и т. д. Нет столкновения, гарантировано уникальное.

С другой стороны, я столкнулся с проблемой "зависания" случайных чисел в цикле, и это произошло потому, что Random не является поточно-ориентированным. Вот как я справился: C # Генератор случайных чисел застрял в цикле

Кроме того, почему бы не добавить код регистрации, чтобы вы могли проверить выводимые случайные числа и проверить, сколько данных уже находится в БД пользователя? (Хотя я почти уверен, что ты уже сделал это)

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

Нет, в статическом методе не будет никакой разницы. Однако, если вы вызовете свой метод несколько раз в течение короткого промежутка времени, вы в конечном итоге создадите одно и то же начальное число. Это, в свою очередь, означает, что вы получите те же значения, полученные из него. Кстати, безпараметрический конструктор Random уже инициализирует себя с текущей даты / времени, поэтому его явное использование избыточно.

Вы должны использовать один экземпляр Random на поток (к сожалению, Random не является потокобезопасным).

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

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

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

Если честно, я не могу представить, почему вы хотели бы случайного в ПК, но эй - это ваше шоу ...

У меня всегда генерируются мои первичные ключи - даже в Oracle, который не так хорош, я использую последовательности для их генерации.

А что касается генерации случайных чисел, см. Ответ Гуффы.

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

Причина в том, что вы создаете Random объектов, которые вы сеете с тем же начальным значением.Когда вы создаете их слишком близко по времени, значение DateTime.Now.Ticks не успевает измениться.

Создайте один Random объект, который вы используете для всех случайных чисел, которые вы хотите создать в классе,Вы можете отправить объект в статический метод в качестве параметра.

Обратите внимание, что иногда вы будете сталкиваться с коллизиями, случайность не гарантирует уникальность.

0 голосов
/ 29 апреля 2010

Расширяя ответ Джона, ваш класс должен быть структурирован так:

static class MyClass
{

    static int iRand = new Random(); // default seed is based on ticks
    static int rand; 

    static void MyMethod()
    {
        rand= rand.Next(50000); 
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...