Генератор случайных строк, возвращающий ту же строку

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

Вот код и пример его вывода:

private string RandomString(int size)
{
    StringBuilder builder = new StringBuilder();
    Random random = new Random();
    char ch;
    for (int i = 0; i < size; i++)
    {
        ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));                 
        builder.Append(ch);
    }

    return builder.ToString();
}

// get 1st random string 
string Rand1 = RandomString(4);

// get 2nd random string 
string Rand2 = RandomString(4);

// create full rand string
string docNum = Rand1 + "-" + Rand2;

... и результат выглядит так: UNTE-UNTE ... но он должен выглядеть примерно так: UNTE-FWNU

Как я могу гарантировать, что две совершенно случайные строки?


person PushCode    schedule 13.07.2009    source источник
comment
stackoverflow.com/questions/4616685/ Хорошая производительность   -  person mola10    schedule 02.11.2011
comment
Обратите внимание, что даже две совершенно случайные строки не могут быть уникальными. С длинными строками (120+ бит) очень вероятно, что они уникальны, но с такими короткими строками, как эта, конфликты являются обычным явлением.   -  person CodesInChaos    schedule 19.11.2012
comment
Старый поток, но ... если он подходит, вы можете сгенерировать GUID и преобразовать его в текст.   -  person user3657408    schedule 28.02.2020


Ответы (30)


Вы создаете экземпляр Random в методе, что заставляет его возвращать те же значения при быстром последовательном вызове. Я бы сделал что-то вроде этого:

private static Random random = new Random((int)DateTime.Now.Ticks);//thanks to McAden
private string RandomString(int size)
    {
        StringBuilder builder = new StringBuilder();
        char ch;
        for (int i = 0; i < size; i++)
        {
            ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));                 
            builder.Append(ch);
        }

        return builder.ToString();
    }

// get 1st random string 
string Rand1 = RandomString(4);

// get 2nd random string 
string Rand2 = RandomString(4);

// creat full rand string
string docNum = Rand1 + "-" + Rand2;

(измененная версия вашего кода)

person RCIX    schedule 13.07.2009
comment
Обратите внимание, что члены экземпляра класса Random НЕ задокументированы как потокобезопасные, поэтому, если этот метод вызывается из нескольких потоков одновременно (весьма вероятно, например, если вы создаете веб-приложение), то поведение этого код будет неопределенным. Вам нужно либо использовать блокировку случайного, либо сделать ее для каждого потока. - person Greg Beech; 14.10.2010
comment
да, random не является потокобезопасным и вызывает множество проблем на сайте asp.net - person MonsterMMORPG; 26.12.2012
comment
Кроме того, вы можете получить случайную заглавную букву, используя ch = (char)random.Next('A','Z'); намного проще, чем нечитаемую строку ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))); из исходного сообщения. Затем, если вы хотите переключить его на нижний регистр, вы можете легко переключиться на (char)random.Next('a','z'); - person Nick Freeman; 11.04.2013
comment
@NickFreeman: помните, что верхняя граница является исключительной, поэтому ch = (char)random.Next('A','Z'); никогда не будет вернуть 'Z'. Таким образом, вам понадобится ch = (char)random.Next('A', 'Z' + 1);, чтобы включить 'Z'. - person T.J. Crowder; 30.05.2013
comment
При последовательном вызове выдает ту же букву. - person shubniggurath; 10.01.2014
comment
Возможный способ linq: Enumerable.Range (0,4) .Select (c = ›(char) rand.Next ('a', 'z' + 1)). ToArray (); - person Jason Slocomb; 10.03.2014
comment
На самом деле я использую new Random(Guid.NewGuid().GetHashCode()); в качестве начального числа вместо того, чтобы полагаться на DateTime. - person Filipe Leite; 07.11.2014

Вы создаете экземпляр объекта Random внутри своего метода.

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

Чтобы решить эту проблему, переместите свой экземпляр Random за пределы самого метода (и пока вы работаете с ним, вы можете избавиться от этой сумасшедшей последовательности вызовов Convert, Floor и NextDouble):

private readonly Random _rng = new Random();
private const string _chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private string RandomString(int size)
{
    char[] buffer = new char[size];

    for (int i = 0; i < size; i++)
    {
        buffer[i] = _chars[_rng.Next(_chars.Length)];
    }
    return new string(buffer);
}
person LukeH    schedule 13.07.2009
comment
Или сделайте его статическим и внутренним по отношению к классу. - person Jake Pearson; 14.07.2009
comment
Кроме того, мне нравится делать этот вид метода методом расширения в Random. - person Cameron MacFarland; 14.07.2009
comment
Обратите внимание, что члены экземпляра класса Random НЕ задокументированы как потокобезопасные, поэтому, если этот метод вызывается из нескольких потоков одновременно (весьма вероятно, если вы создаете веб-приложение, например), то поведение этого код будет неопределенным. Вам нужно либо использовать блокировку случайного, либо сделать ее для каждого потока. - person Greg Beech; 14.10.2010

Очень простая реализация, использующая Path.GetRandomFileName():

using System.IO;   
public static string RandomStr()
{
    string rStr = Path.GetRandomFileName();
    rStr = rStr.Replace(".", ""); // For Removing the .
    return rStr;
}

Теперь просто позвоните RandomStr().

person Ranvir    schedule 09.11.2010
comment
Мне этот метод нравится больше, чем другие перечисленные. Хорошая находка. - person Graham; 18.04.2011
comment
Ницца! Обожаю, когда находишь такую ​​маленькую жемчужину, как GetRandomFileName, спрятанную в платформе .Net. - person Andy Britcliffe; 20.04.2011
comment
+1 - Использовал это сегодня - в восторге! - person LeopardSkinPillBoxHat; 20.12.2011
comment
Использовал ваш с небольшими изменениями. guid = Guid.NewGuid (); mystring = guid.ToString (); mystring = mystring.Replace (-,); mystring = mystring.Substring (0, 8); - person Andrew; 13.01.2012
comment
@Andrew Вы, вероятно, немного уменьшите случайность, если используете только подстроку guid. - person Anders Fjeldstad; 23.01.2012
comment
@AndersFjeldstad Согласен, я выполнил цикл, и он попадает в коллизию примерно после 130 000 итераций. Хотя есть 1 785 793 904 896 комбинаций. - person Andrew; 24.01.2012
comment
Это создает файлы на диске. Из MSDN: метод GetTempFileName вызовет исключение IOException, если он используется для создания более 65535 файлов без удаления предыдущих временных файлов. Метод GetTempFileName вызовет исключение IOException, если уникальное имя временного файла недоступно. Чтобы устранить эту ошибку, удалите все ненужные временные файлы. - person bugnuker; 25.07.2012
comment
@bugnuker Метод GetRandomFileName возвращает криптографически стойкую случайную строку, которую можно использовать как имя папки или имя файла. В отличие от GetTempFileName, GetRandomFileName не создает файл. Когда безопасность вашей файловой системы имеет первостепенное значение, этот метод следует использовать вместо GetTempFileName. Мы говорим о GetRandomFileName (), а не о GetTempFileName (). - person quantum; 07.11.2012
comment
Умно, красиво и просто. Люблю это: P - person Ignacio Soler Garcia; 21.06.2013

Если вы используете Asp.Net 2.0 или выше, вы также можете использовать вызов библиотеки - System.Web.Security.Membership.GeneratePassword, однако он будет включать специальные символы.

Чтобы получить 4 случайных символа с минимум 0 специальными символами -

Membership.GeneratePassword(4, 0)
person Spongeboy    schedule 23.03.2011
comment
Обратите внимание, что в 4.0 второй целочисленный параметр обозначает минимальное количество nonAlphaNumericCharacters для использования. Таким образом, Membership.GeneratePassword(10, 0); не будет работать так, как вы думаете, он по-прежнему вставляет множество не буквенно-цифровых символов, например: z9sge)?pmV - person keithl8041; 19.08.2011
comment
единственная причина, по которой я могу думать о том, что не хочу использовать это по сравнению с другими методами, - это хлопоты, которые вам нужно пройти, чтобы удалить специальные символы ....... при условии, что вам нужно, чего я не - person Ben; 17.04.2012
comment
Спасибо keithl8041, обновленный ответ, чтобы отразить это. - person Spongeboy; 12.06.2012
comment
Для меня это правильный ответ, если у вас есть доступ к членству. Я имею в виду, зачем изобретать горячую воду, верно? - person Marko; 23.02.2013

Просто для людей, которые заходят, и зачем иметь случайную строку всего в одной строчке кода

int yourRandomStringLength = 12; //maximum: 32
Guid.NewGuid().ToString("N").Substring(0, yourRandomStringLength);

PS: Имейте в виду, что yourRandomStringLength не может превышать 32, так как Guid имеет максимальную длину 32.

person Abdul Munim    schedule 18.01.2012
comment
Я не уверен, что это обязательно будет случайным образом. Идентификаторы GUID должны быть уникальными, а не случайными, поэтому возможно, что первые N символов в строке могут быть идентичными (в зависимости от генератора GUID). - person cdmckay; 25.06.2012
comment
Мне просто нужен был временный пароль из 5 символов для хеширования. Это чудесно, спасибо. - person Bmo; 23.10.2012

Это решение является расширением для класса Random.

использование

class Program
{
    private static Random random = new Random(); 

    static void Main(string[] args)
    {
        random.NextString(10); // "cH*%I\fUWH0"
        random.NextString(10); // "Cw&N%27+EM"
        random.NextString(10); // "0LZ}nEJ}_-"
        random.NextString();   // "kFmeget80LZ}nEJ}_-"
    }
}

Выполнение

public static class RandomEx
{
    /// <summary>
    /// Generates random string of printable ASCII symbols of a given length
    /// </summary>
    /// <param name="r">instance of the Random class</param>
    /// <param name="length">length of a random string</param>
    /// <returns>Random string of a given length</returns>
    public static string NextString(this Random r, int length)
    {
        var data = new byte[length];
        for (int i = 0; i < data.Length; i++)
        {
            // All ASCII symbols: printable and non-printable
            // data[i] = (byte)r.Next(0, 128);
            // Only printable ASCII
            data[i] = (byte)r.Next(32, 127);
        }
        var encoding = new ASCIIEncoding();
        return encoding.GetString(data);
    }

    /// <summary>
    /// Generates random string of printable ASCII symbols
    /// with random length of 10 to 20 chars
    /// </summary>
    /// <param name="r">instance of the Random class</param>
    /// <returns>Random string of a random length between 10 and 20 chars</returns>
    public static string NextString(this Random r)
    {
        int length  = r.Next(10, 21);
        return NextString(r, length);
    }
}
person oleksii    schedule 30.12.2011
comment
Вы тянете из всего набора ascii, включая непечатаемые символы? - person Nicholi; 06.11.2012
comment
Я добавил диапазон только для печатных символов. Вам нужно будет прокомментировать одну строку и раскомментировать другую. Спасибо. - person oleksii; 06.11.2012

Еще одна версия генератора строк. Просто, без вычурной математики и волшебных цифр. Но с какой-то волшебной строкой, в которой указаны разрешенные символы.

Обновление: я сделал генератор статическим, поэтому он не будет возвращать одну и ту же строку при многократном вызове. Однако этот код не потокобезопасен и определенно не криптографически безопасен.

Для генерации пароля должен быть System.Security.Cryptography.RNGCryptoServiceProvider использовал.

private Random _random = new Random(Environment.TickCount);

public string RandomString(int length)
{
    string chars = "0123456789abcdefghijklmnopqrstuvwxyz";
    StringBuilder builder = new StringBuilder(length);

    for (int i = 0; i < length; ++i)
        builder.Append(chars[_random.Next(chars.Length)]);

    return builder.ToString();
}
person Maksym Davydov    schedule 24.09.2012
comment
это сгенерирует одну и ту же строку, если вы вызовете ее несколько раз .. - person stian.net; 08.05.2013
comment
Спасибо @ stian.net, генератор статичный сделал. - person Maksym Davydov; 23.05.2013

Вот еще один вариант:

public System.String GetRandomString(System.Int32 length)
{
    System.Byte[] seedBuffer = new System.Byte[4];
    using (var rngCryptoServiceProvider = new System.Security.Cryptography.RNGCryptoServiceProvider())
    {
        rngCryptoServiceProvider.GetBytes(seedBuffer);
        System.String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        System.Random random = new System.Random(System.BitConverter.ToInt32(seedBuffer, 0));
        return new System.String(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
    }
}
person Zygimantas    schedule 17.06.2013

Лучшее решение - использовать генератор случайных чисел вместе с преобразованием base64.

public string GenRandString(int length)
{
  byte[] randBuffer = new byte[length];
  RandomNumberGenerator.Create().GetBytes(randBuffer);
  return System.Convert.ToBase64String(randBuffer).Remove(length);
}
person Ami Luttwak    schedule 22.09.2012
comment
Обратите внимание, что результат может содержать / и +. - person CodesInChaos; 19.11.2012
comment
Истинный. Однако я предпочитаю это членству .GeneratePassword () - person Aaron Azhari; 18.12.2012
comment
return System.Convert.ToBase64String (randBuffer) .Replace (/,) .Replace (+,) .Replace (=,) .Remove (длина); - person mjb; 06.01.2013

Однострочный LINQ для хорошей меры (при условии _1 _) ...

public static string RandomString(int length)
{
    return new string(Enumerable.Range(0, length).Select(_ => (char)Random.Next('a', 'z')).ToArray());
}
person AlexFoxGill    schedule 12.08.2013

Это потому, что каждый новый экземпляр Random генерирует одни и те же числа из-за столь быстрого вызова. Не продолжайте создавать новый экземпляр, просто вызовите next () и объявите свой случайный класс вне вашего метода.

person John T    schedule 13.07.2009

У вас должен быть один объект Random уровня класса, инициируемый один раз в конструкторе и повторно используемый при каждом вызове (это продолжает ту же последовательность псевдослучайных чисел). Конструктор без параметров уже внутренне заполняет генератор Environment.TickCount.

person Kenan E. K.    schedule 13.07.2009

Если вы хотите создать строку цифр и символов для надежного пароля.

private static Random random = new Random();

private static string CreateTempPass(int size)
        {
            var pass = new StringBuilder();
            for (var i=0; i < size; i++)
            {
                var binary = random.Next(0,2);
                switch (binary)
                {
                    case 0:
                    var ch = (Convert.ToChar(Convert.ToInt32(Math.Floor(26*random.NextDouble() + 65))));
                        pass.Append(ch);
                        break;
                    case 1:
                        var num = random.Next(1, 10);
                        pass.Append(num);
                        break;
                }
            }
            return pass.ToString();
        }
person CGsoldier    schedule 14.10.2010
comment
Обратите внимание, что члены экземпляра класса Random НЕ задокументированы как потокобезопасные, поэтому, если этот метод вызывается из нескольких потоков одновременно (весьма вероятно, если вы создаете веб-приложение, например), то поведение этого код будет неопределенным. Вам нужно либо использовать блокировку случайного, либо сделать ее для каждого потока. - person Greg Beech; 14.10.2010
comment
@GregBeech правда? Снова? Скучно? - person Jimmy D; 31.12.2011

Я добавил возможность выбора длины с помощью раствора Ранвира.

public static string GenerateRandomString(int length)
    {
        {
            string randomString= string.Empty;

            while (randomString.Length <= length)
            {
                randomString+= Path.GetRandomFileName();
                randomString= randomString.Replace(".", string.Empty);
            }

            return randomString.Substring(0, length);
        }
    }
person João Miguel    schedule 27.03.2012

Вот моя модификация принятого в настоящее время ответа, который, я считаю, немного быстрее и короче:

private static Random random = new Random();

private string RandomString(int size) {
    StringBuilder builder = new StringBuilder(size);
    for (int i = 0; i < size; i++)
        builder.Append((char)random.Next(0x41, 0x5A));
    return builder.ToString();
}

Обратите внимание, я не использовал все умножение, Math.floor(), Convert и т. Д.

РЕДАКТИРОВАТЬ: random.Next(0x41, 0x5A) можно изменить на любой диапазон символов Юникода.

person quantum    schedule 01.11.2012
comment
psst ... вы на самом деле не ответили на проблему, которая была у OP ... - person Andrew Barber; 01.11.2012
comment
@Andrew Это действительно решает проблему, обратите внимание, что это также оптимизация, которую я сделал для принятого ответа. - person quantum; 01.11.2012
comment
Ваш код делает. Однако в вашем описании об этом не упоминается. Что касается оптимизации; Прежде чем соглашаться с этим утверждением, я хотел бы увидеть несколько тестов; происходит что-то, о чем вы (по-видимому) не подозреваете. Как неявные преобразования. Кроме того, вы пропустили потенциально самый большой прирост производительности - указание начального размера для StringBuilder. (ПО МОЕМУ МНЕНИЮ) - person Andrew Barber; 01.11.2012
comment
@Andrew Я изменю свой ответ, чтобы отразить это, но с генерацией равномерно распределенного с помощью метода, предоставляемого .NET, вместо пользовательского метода, включающего операцию умножения и минимума, должно быть быстрее. - person quantum; 01.11.2012

Мой RandomString() метод генерации случайной строки.

private static readonly Random _rand = new Random();

/// <summary>
/// Generate a random string.
/// </summary>
/// <param name="length">The length of random string. The minimum length is 3.</param>
/// <returns>The random string.</returns>
public string RandomString(int length)
{
    length = Math.Max(length, 3);

    byte[] bytes = new byte[length];
    _rand.NextBytes(bytes);
    return Convert.ToBase64String(bytes).Substring(0, length);
}
person AechoLiu    schedule 25.06.2013

Думаю, может быть, это тоже приемлемо и просто.

Guid.NewGuid().ToString() 
person wener    schedule 29.10.2013
comment
Не гарантируется, что GUID будут случайными, поэтому вы не должны использовать их как ГПСЧ. Текущая реализация в Windows случайна, но в более старых версиях она была основана на MAC-адресе и времени. Кто знает, какие будущие версии будут использовать. - person CodesInChaos; 29.10.2013
comment
Я так не думаю. В настоящее время многие люди используют GUID в качестве первичного ключа, и да, GUID может конфликтовать, но 2^128 записано примерно: 34,028,236,692,093,846,346,337,460,743,177,000,000. По статистике, если вы рассчитываете 1000 GUID каждую секунду, на получение дубликата все равно уйдут триллионы лет. TWW, использовать guid настолько просто, что я не думаю, что это плохая идея. - person wener; 29.10.2013
comment
Суть GUID в том, что он уникален, а не случайен. Если бы вы использовали его в качестве уникального идентификатора, я бы не стал жаловаться, но вы продаете его как случайную строку, что и есть сейчас, но не гарантирует. (И благодаря проблеме дня рождения вам нужно всего около 2 ^ 61 значений, чтобы найти дубликат, а не 2 ^ 122, так что ваши триллионы лет на самом деле составляют всего около 75 миллионов лет) - person CodesInChaos; 29.10.2013
comment
Это может генерировать случайную строку, вот и все, но не может генерировать ту же самую последовательность. - person wener; 14.02.2014
comment
В текущей реализации происходит генерация в основном случайной строки (ее части не случайны). Не гарантируется, что это будет случайным, прошлые реализации не были случайными, и будущие реализации также могут быть не случайными. - person CodesInChaos; 17.02.2014

Объединение ответа «Pushcode» и ответа, использующего начальное число для генератора случайных чисел. Мне это было нужно для создания серии псевдочитаемых «слов».

private int RandomNumber(int min, int max, int seed=0)
{
    Random random = new Random((int)DateTime.Now.Ticks + seed);
    return random.Next(min, max);
}
person Ideogram    schedule 23.09.2011
comment
C # не имеет аргументов по умолчанию AFAIK. - person quantum; 01.11.2012
comment
@xiaomao Вы не правы. Я использую их все время. Кстати, они называются необязательными аргументами. - person Andrew Barber; 01.11.2012
comment
@Andrew Хорошо, это новое дополнение от MSDN: Visual C # 2010 вводит именованные и необязательные аргументы. - person quantum; 01.11.2012
comment
@xiaomao Я бы не стал называть более 3-х лет и одну предыдущую полную версию новым дополнением. К тому времени, когда в сентябре прошлого года был опубликован этот ответ, это была хорошо известная функция. - person Andrew Barber; 01.11.2012

Я создал этот метод.

Работает отлично.

public static string GeneratePassword(int Lenght, int NonAlphaNumericChars)
    {
        string allowedChars = "abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789";
        string allowedNonAlphaNum = "!@#$%^&*()_-+=[{]};:<>|./?";
        Random rd = new Random();

        if (NonAlphaNumericChars > Lenght || Lenght <= 0 || NonAlphaNumericChars < 0)
            throw new ArgumentOutOfRangeException();

            char[] pass = new char[Lenght];
            int[] pos = new int[Lenght];
            int i = 0, j = 0, temp = 0;
            bool flag = false;

            //Random the position values of the pos array for the string Pass
            while (i < Lenght - 1)
            {
                j = 0;
                flag = false;
                temp = rd.Next(0, Lenght);
                for (j = 0; j < Lenght; j++)
                    if (temp == pos[j])
                    {
                        flag = true;
                        j = Lenght;
                    }

                if (!flag)
                {
                    pos[i] = temp;
                    i++;
                }
            }

            //Random the AlphaNumericChars
            for (i = 0; i < Lenght - NonAlphaNumericChars; i++)
                pass[i] = allowedChars[rd.Next(0, allowedChars.Length)];

            //Random the NonAlphaNumericChars
            for (i = Lenght - NonAlphaNumericChars; i < Lenght; i++)
                pass[i] = allowedNonAlphaNum[rd.Next(0, allowedNonAlphaNum.Length)];

            //Set the sorted array values by the pos array for the rigth posistion
            char[] sorted = new char[Lenght];
            for (i = 0; i < Lenght; i++)
                sorted[i] = pass[pos[i]];

            string Pass = new String(sorted);

            return Pass;
    }
person Hugo    schedule 15.05.2012
comment
Еще раз показывает, что безопасность сложно проверить. Хотя он отлично работает, это небезопасно. Используйте безопасный ГПСЧ для генерации паролей. - person CodesInChaos; 19.11.2012

А вот еще одна идея, основанная на GUID. Я использовал его для Visual Studio тест производительности для генерации случайной строки, содержащей только буквенно-цифровые символы.

public string GenerateRandomString(int stringLength)
{
    Random rnd = new Random();
    Guid guid;
    String randomString = string.Empty;

    int numberOfGuidsRequired = (int)Math.Ceiling((double)stringLength / 32d);
    for (int i = 0; i < numberOfGuidsRequired; i++)
    {
        guid = Guid.NewGuid();
        randomString += guid.ToString().Replace("-", "");
    }

    return randomString.Substring(0, stringLength);
}
person Maciej Zaleski    schedule 19.06.2012

public static class StringHelpers
{
    public static readonly Random rnd = new Random();

    public static readonly string EnglishAlphabet = "abcdefghijklmnopqrstuvwxyz";
    public static readonly string RussianAlphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя";

    public static unsafe string GenerateRandomUTF8String(int length, string alphabet)
    {
        if (length <= 0)
            return String.Empty;
        if (string.IsNullOrWhiteSpace(alphabet))
            throw new ArgumentNullException("alphabet");

        byte[] randomBytes = rnd.NextBytes(length);

        string s = new string(alphabet[0], length);

        fixed (char* p = s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                *(p + i) = alphabet[randomBytes[i] % alphabet.Length];
            }
        }
        return s;
    }

    public static unsafe string GenerateRandomUTF8String(int length, params UnicodeCategory[] unicodeCategories)
    {
        if (length <= 0)
            return String.Empty;
        if (unicodeCategories == null)
            throw new ArgumentNullException("unicodeCategories");
        if (unicodeCategories.Length == 0)
            return rnd.NextString(length);

        byte[] randomBytes = rnd.NextBytes(length);

        string s = randomBytes.ConvertToString();
        fixed (char* p = s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                while (!unicodeCategories.Contains(char.GetUnicodeCategory(*(p + i))))
                    *(p + i) += (char)*(p + i);
            }
        }
        return s;
    }
}

Также вам понадобится:

public static class RandomExtensions
{
    public static string NextString(this Random rnd, int length)
    {
        if (length <= 0)
            return String.Empty;

        return rnd.NextBytes(length).ConvertToString();
    }

    public static byte[] NextBytes(this Random rnd, int length)
    {
        if (length <= 0)
            return new byte[0];

        byte[] randomBytes = new byte[length];
        rnd.NextBytes(randomBytes);
        return randomBytes;
    }
}

И это:

public static class ByteArrayExtensions
{
    public static string ConvertToString(this byte[] bytes)
    {
        if (bytes.Length <= 0)
            return string.Empty;

        char[] chars = new char[bytes.Length / sizeof(char)];
        Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }
}
person Konard    schedule 16.04.2013

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

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

Здесь есть 3 примера: http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx.

Я бы использовал последний:

public static class RandomGen3
{
    private static RNGCryptoServiceProvider _global = 
        new RNGCryptoServiceProvider();
    [ThreadStatic]
    private static Random _local;

    public static int Next()
    {
        Random inst = _local;
        if (inst == null)
        {
            byte[] buffer = new byte[4];
            _global.GetBytes(buffer);
            _local = inst = new Random(
                BitConverter.ToInt32(buffer, 0));
        }
        return inst.Next();
    }
}

Тогда вы сможете правильно устранить

Random random = new Random();

И просто вызовите RandomGen3.Next (), пока ваш метод может оставаться статическим.

person Stefan Steiger    schedule 23.05.2013

Для генератора случайных строк:

#region CREATE RANDOM STRING WORD
        char[] wrandom = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','R','S','T','U','V','X','W','Y','Z'};
        Random random = new Random();
        string random_string = "";
        int count = 12; //YOU WILL SPECIFY HOW MANY CHARACTER WILL BE GENERATE
        for (int i = 0; i < count; i++ )
        {
            random_string = random_string + wrandom[random.Next(0, 24)].ToString(); 
        }
        MessageBox.Show(random_string);
        #endregion
person Toprak    schedule 02.01.2014

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

static string
    numbers = "0123456789",
    letters = "abcdefghijklmnopqrstvwxyz",
    lettersUp = letters.ToUpper(),
    codeAll = numbers + letters + lettersUp;

static Random m_rand = new Random();

public static string GenerateCode(this int size)
{
    return size.GenerateCode(CodeGeneratorType.All);
}

public static string GenerateCode(this int size, CodeGeneratorType type)
{
    string source;

    if (type == CodeGeneratorType.All)
    {
        source = codeAll;
    }
    else
    {
        StringBuilder sourceBuilder = new StringBuilder();
        if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.Numbers)
            sourceBuilder.Append(numbers);
        if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.Letters)
            sourceBuilder.Append(letters);
        if ((type & CodeGeneratorType.Letters) == CodeGeneratorType.LettersUpperCase)
            sourceBuilder.Append(lettersUp);

        source = sourceBuilder.ToString();
    }

    return size.GenerateCode(source);
}

public static string GenerateCode(this int size, string source)
{
    StringBuilder code = new StringBuilder();
    int maxIndex = source.Length-1;
    for (int i = 0; i < size; i++)
    {

        code.Append(source[Convert.ToInt32(Math.Round(m_rand.NextDouble() * maxIndex))]);
    }

    return code.ToString();
}

public enum CodeGeneratorType { Numbers = 1, Letters = 2, LettersUpperCase = 4, All = 16 };

Надеюсь это поможет.

person WhyMe    schedule 07.04.2013

В моей ситуации пароль должен содержать:

  • Хотя бы один нижний регистр.
  • Хотя бы один верхний регистр.
  • Хотя бы один десятичный знак.
  • По крайней мере, один специальный символ.

Вот мой код:

    private string CreatePassword(int len)
    {
        string[] valid = { "abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "1234567890", "!@#$%^&*()_+" };
        RNGCryptoServiceProvider rndGen = new RNGCryptoServiceProvider();

        byte[] random = new byte[len];
        int[] selected = new int[len];

        do
        {
            rndGen.GetNonZeroBytes(random);

            for (int i = 0; i < random.Length; i++)
            {
                selected[i] = random[i] % 4;
            }
        } 
        while(selected.Distinct().Count() != 4);

        rndGen.GetNonZeroBytes(random);

        string res = "";

        for(int i = 0; i<len; i++)
        {
            res += valid[selected[i]][random[i] % valid[selected[i]].Length];
        }
        return res;
    }
person Jules    schedule 12.12.2013

Здравствуйте,
вы можете использовать WordGenerator или LoremIpsumGenerator из пакета nuget MMLib.RapidPrototyping.

using MMLib.RapidPrototyping.Generators;
public void WordGeneratorExample()
{
   WordGenerator generator = new WordGenerator();
   var randomWord = generator.Next();

   Console.WriteLine(randomWord);
} 

сайт Nuget
Сайт проекта Codeplex

person Mino    schedule 30.12.2013

Если у вас есть доступ к процессору, совместимому с Intel Secure Key, вы можете генерировать реальные случайные числа и строки с помощью этих библиотек: https://github.com/JebteK/RdRand и https://www.rdrand.com/

Просто загрузите последнюю версию с здесь, включите Jebtek.RdRand и добавьте оператор using для этого. Затем все, что вам нужно сделать, это:

bool isAvailable = RdRandom.GeneratorAvailable(); //Check to see if this is a compatible CPU
string key = RdRandom.GenerateKey(10); //Generate 10 random characters

Кроме того, вы также получаете следующие дополнительные возможности:

string apiKey = RdRandom.GenerateAPIKey(); //Generate 64 random characters, useful for API keys
byte[] b = RdRandom.GenerateBytes(10); //Generate an array of 10 random bytes
uint i = RdRandom.GenerateUnsignedInt() //Generate a random unsigned int

Если у вас нет совместимого процессора для выполнения кода, просто используйте службы RESTful на rdrand.com. С библиотекой оболочки RdRandom, включенной в ваш проект, вам просто нужно сделать это (вы получаете 1000 бесплатных звонков при регистрации):

string ret = Randomizer.GenerateKey(<length>, "<key>");

Вы также можете генерировать случайные байтовые массивы и целые числа без знака следующим образом:

uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
person JebaDaHut    schedule 02.04.2014

Другой образец (протестирован в 2013 году):

    Random R = new Random();
    public static string GetRandomString(int Length)
    {
        char[] ArrRandomChar = new char[Length];
        for (int i = 0; i < Length; i++)
            ArrRandomChar[i] = (char)('a' + R.Next(0, 26));
        return new string(ArrRandomChar);
    }

    string D = GetRandomString(12);

Реализовал сам.

person Amin Ghaderi    schedule 27.05.2014

Это мое решение:

private string RandomString(int length)
{
    char[] symbols = { 
                            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'                             
                        };

    Stack<byte> bytes = new Stack<byte>();
    string output = string.Empty;

    for (int i = 0; i < length; i++)
    {
        if (bytes.Count == 0)
        {
            bytes = new Stack<byte>(Guid.NewGuid().ToByteArray());
        }
        byte pop = bytes.Pop();
        output += symbols[(int)pop % symbols.Length];
    }
    return output;
}

// get 1st random string 
string Rand1 = RandomString(4);

// get 2nd random string 
string Rand2 = RandomString(4);

// create full rand string
string docNum = Rand1 + "-" + Rand2;
person ADM-IT    schedule 26.12.2014

И еще одна версия: я использовал этот метод для генерации случайных псевдосимволов акций при тестировании:

Random rand = new Random();
Func<char> randChar = () => (char)rand.Next(65, 91); // upper case ascii codes
Func<int,string> randStr = null;
    randStr = (x) => (x>0) ? randStr(--x)+randChar() : ""; // recursive

Использование:

string str4 = randStr(4);// generates a random 4 char string
string strx = randStr(rand.next(1,5)); // random string between 1-4 chars in length

Вы можете переопределить функцию randChar для использования с «разрешенным» массивом символов по позиции вместо кода ascii:

char[] allowedchars = {'A','B','C','1','2','3'};
Func<char> randChar = () => allowedchars[rand.Next(0, allowedchars.Length-1)];
person cramroop    schedule 23.04.2014