почему этот метод каждый раз возвращает одну и ту же случайную строку?
Вопрос
Мне нужно создать блок уникальных строк, чтобы протестировать другой проект, над которым я работаю.
Поэтому я создал простую программу для генерации случайной строки длины X.
Проблема в том, что если я вызову его один раз, я получу случайную строку, если я вызову его снова (например, в цикле for), я получу ту же строку для всего выполнения цикла.
У меня такое ощущение, что оно кэшируется или что-то в этом роде, но я не знал, что .net это сделал, и сейчас я просто в замешательстве.
код вызова:
StreamWriter SW = new StreamWriter("c:\\test.txt");
int x = 100;
while (x >0)
{
SW.WriteLine(RandomString(20));
x--;
}
вот метод:
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
Random randomNumber = new Random();
for (int i = 0; i <= Length; ++i)
{
int x = randomNumber.Next(65, 122);
sb.Append(Convert.ToChar(x));
}
return sb.ToString();
}
и вот результат:
"VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
..................
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB
VEWMCQ`Fw]TvSFQawYnoB"
Итак, что дает мне мысль, что Random.next() всегда будет возвращать новое случайное число?
Решение
Вы создаете Random
случаи слишком близки по времени.Каждый экземпляр инициализируется с использованием системных часов, и, поскольку часы не изменились, вы снова и снова получаете одну и ту же последовательность случайных чисел.
Создайте единственный экземпляр Random
class и используйте его снова и снова.
Использовать using
ключевое слово, чтобы StreamWriter
закрывается и удаляется, когда вы закончите с ним.Код цикла легче распознать, если вы используете for
ключевое слово.
using (StreamWriter SW = new StreamWriter("c:\\test.txt")) {
Random rnd = new Random();
for (int x = 100; x > 0; x--) {
SW.WriteLine(RandomString(rnd, 20));
}
}
Метод принимает Random
объект в качестве параметра.
Кроме того, используйте длину для инициализации StringBuilder с правильной емкостью, чтобы не приходилось перераспределять ее во время цикла.Используйте в цикле оператор < вместо <=, иначе вы создадите строку, которая на один символ длиннее, чем length
параметр указывает.
private static string RandomString(Random rnd, int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
int x = rnd.Next(65, 122);
sb.Append((char)x);
}
return sb.ToString();
}
Другие советы
Видеть Описание случайного конструктора в MSN эта часть:
Значение семян по умолчанию получено из системных часов и имеет конечное разрешение.В результате различные случайные объекты, которые создаются в тесной последовательности при вызове конструктора по умолчанию, будут иметь идентичные значения семян дефолта и, следовательно, будут создавать идентичные наборы случайных чисел.
Поэтому либо вызовите конструктор Random() только один раз в начале вашей программы, либо используйте конструктор Random(int32) и самостоятельно определите изменяющееся начальное число.
Потому что вы создаете новый объект Random при каждом вызове.
Просто переместите случайный номер из метода и сделайте его членом класса.
private Random randomNumber = new Random();
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
//...
}
Все программные генераторы случайных чисел являются «псевдослучайными», они создают последовательность чисел на основе (начального) начального числа.С одним и тем же семенем они производят одну и ту же последовательность.Иногда это полезно.Если вы хотите, чтобы ваша программа создавала одну и ту же последовательность при каждом запуске, вы можете использовать new Random(0)
.
Редактировать:очевидно, что класс .Net Random автоматически заполняется, я этого не знал.Так что, как отмечали другие, это проблема времени.
объявляйте случайное число только один раз
public class MyClass
{
private static Random randomNumber = new Random();
private static string RandomString(int Length)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i ... Length; ++i)
{
int x = MyClass.randomNumber.Next(65, 122);
sb.Append(Convert.ToChar(x));
}
return sb.ToString();
}
}
Аналогичный вопрос, много ответов:
генерация случайной строки - две сгенерированные друг за другом дают одинаковые результаты
все начальные числа для случайных чисел одинаковы из-за короткого промежутка времени, по сути, вы каждый раз заново создаете генератор случайных чисел с одним и тем же начальным числом, поэтому вызов Next() возвращает одно и то же случайное значение.