Come posso generare stringhe alfanumeriche casuali in C #?

Come posso generare stringhe alfanumeriche casuali di 8 caratteri in C #?

Ho sentito che LINQ è il nuovo nero, quindi ecco il mio tentativo di utilizzare LINQ:

 private static Random random = new Random(); public static string RandomString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; return new string(Enumerable.Repeat(chars, length) .Select(s => s[random.Next(s.Length)]).ToArray()); } 

( Nota: l’uso della class Random lo rende inadatto a qualsiasi cosa relativa alla sicurezza, come la creazione di password o token.
Utilizza la class RNGCryptoServiceProvider se hai bisogno di un potente generatore di numeri casuali.)

 var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var stringChars = new char[8]; var random = new Random(); for (int i = 0; i < stringChars.Length; i++) { stringChars[i] = chars[random.Next(chars.Length)]; } var finalString = new String(stringChars); 

Non elegante come la soluzione Linq. (-:

(Nota: l'uso della class Random lo rende inadatto a qualsiasi cosa relativa alla sicurezza , come la creazione di password o token. Utilizza la class RNGCryptoServiceProvider se hai bisogno di un generatore di numeri casuali forte).

Questa implementazione (trovata tramite google) mi sembra valida.

A differenza di alcune delle alternative presentate, questa è crittograficamente valida .

 using System.Security.Cryptography; using System.Text; namespace UniqueKey { public class KeyGenerator { public static string GetUniqueKey(int maxSize) { char[] chars = new char[62]; chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray(); byte[] data = new byte[1]; using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider()) { crypto.GetNonZeroBytes(data); data = new byte[maxSize]; crypto.GetNonZeroBytes(data); } StringBuilder result = new StringBuilder(maxSize); foreach (byte b in data) { result.Append(chars[b % (chars.Length)]); } return result.ToString(); } } } 

Scelto quello da una discussione di alternative qui

Soluzione 1: la più ampia “gamma” con la massima flessibilità

 string get_unique_string(int string_length) { using(var rng = new RNGCryptoServiceProvider()) { var bit_count = (string_length * 6); var byte_count = ((bit_count + 7) / 8); // rounded up var bytes = new byte[byte_count]; rng.GetBytes(bytes); return Convert.ToBase64String(bytes); } } 

Questa soluzione ha più portata rispetto all’utilizzo di un GUID perché un GUID ha un paio di bit fissi che sono sempre gli stessi e quindi non casuali, ad esempio il 13 caratteri in esadecimale è sempre “4” – almeno in un GUID versione 6.

Questa soluzione consente inoltre di generare una stringa di qualsiasi lunghezza.

Soluzione 2: una riga di codice, valida per un massimo di 22 caratteri

 Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0, 8); 

Non è ansible generare stringhe finché la Soluzione 1 e la stringa non hanno lo stesso intervallo a causa di bit fissi nei GUID, ma in molti casi ciò farà il lavoro.

Soluzione 3 – Codice leggermente inferiore

 Guid.NewGuid().ToString("n").Substring(0, 8); 

Per lo più mantenendo questo qui per scopi storici. Usa un po ‘meno codice, che però si presenta come la spesa di avere un raggio inferiore – perché usa hex invece di base64 richiede più caratteri per rappresentare la stessa gamma rispetto alle altre soluzioni.

Il che significa più possibilità di collisione: testarlo con 100.000 iterazioni di stringhe di 8 caratteri genera un duplicato.

Ecco un esempio che ho rubato dall’esempio di Sam Allen a Dot Net Perls

Se sono necessari solo 8 caratteri, utilizzare Path.GetRandomFileName () nello spazio dei nomi System.IO. Sam dice che usare il metodo “Path.GetRandomFileName qui è talvolta superiore, perché usa RNGCryptoServiceProvider per una migliore casualità, tuttavia è limitato a 11 caratteri casuali.”

GetRandomFileName restituisce sempre una stringa di 12 caratteri con un punto al nono carattere. Quindi dovrai rimuovere il punto (poiché non è casuale) e quindi prendere 8 caratteri dalla stringa. In realtà, potresti solo prendere i primi 8 caratteri e non preoccuparti del periodo.

 public string Get8CharacterRandomString() { string path = Path.GetRandomFileName(); path = path.Replace(".", ""); // Remove period. return path.Substring(0, 8); // Return 8 character string } 

PS: grazie Sam

Gli obiettivi principali del mio codice sono:

  1. La distribuzione delle stringhe è quasi uniforms (non preoccuparti delle piccole deviazioni, purché piccole)
  2. Produce più di qualche miliardo di stringhe per ogni argomento impostato. La generazione di una stringa di 8 caratteri (~ 47 bit di entropia) non ha senso se il PRNG genera solo 2 miliardi (31 bit di entropia) di valori diversi.
  3. È sicuro, dal momento che mi aspetto che le persone lo usino per password o altri token di sicurezza.

La prima proprietà si ottiene prendendo un valore a 64 bit modulo la dimensione dell’alfabeto. Per piccoli alfabeti (come i 62 caratteri della domanda) questo porta a pregiudizi trascurabili. La seconda e la terza proprietà vengono raggiunte utilizzando RNGCryptoServiceProvider anziché System.Random .

 using System; using System.Security.Cryptography; public static string GetRandomAlphanumericString(int length) { const string alphanumericCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789"; return GetRandomString(length, alphanumericCharacters); } public static string GetRandomString(int length, IEnumerable characterSet) { if (length < 0) throw new ArgumentException("length must not be negative", "length"); if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody throw new ArgumentException("length is too big", "length"); if (characterSet == null) throw new ArgumentNullException("characterSet"); var characterArray = characterSet.Distinct().ToArray(); if (characterArray.Length == 0) throw new ArgumentException("characterSet must not be empty", "characterSet"); var bytes = new byte[length * 8]; new RNGCryptoServiceProvider().GetBytes(bytes); var result = new char[length]; for (int i = 0; i < length; i++) { ulong value = BitConverter.ToUInt64(bytes, i * 8); result[i] = characterArray[value % (uint)characterArray.Length]; } return new string(result); } 

Il più semplice:

 public static string GetRandomAlphaNumeric() { return Path.GetRandomFileName().Replace(".", "").Substring(0, 8); } 

È ansible ottenere prestazioni migliori se si codifica l’array di caratteri e si fa affidamento su System.Random :

 public static string GetRandomAlphaNumeric() { var chars = "abcdefghijklmnopqrstuvwxyz0123456789"; return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray()); } 

Se mai ti preoccupi, gli alfabeti inglesi possono cambiare a un certo punto e potresti perdere business, quindi puoi evitare l’hard coding, ma dovresti eseguire un po ‘peggio (paragonabile all’approccio Path.GetRandomFileName )

 public static string GetRandomAlphaNumeric() { var chars = 'a'.To('z').Concat('0'.To('9')).ToList(); return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray()); } public static IEnumerable To(this char start, char end) { if (end < start) throw new ArgumentOutOfRangeException("the end char should not be less than start char", innerException: null); return Enumerable.Range(start, end - start + 1).Select(i => (char)i); } 

Gli ultimi due approcci sembrano migliori se puoi renderli un metodo di estensione System.Random .

Solo alcuni confronti delle prestazioni delle varie risposte in questo thread:

Metodi e installazione

 // what's available public static string possibleChars = "abcdefghijklmnopqrstuvwxyz"; // optimized (?) what's available public static char[] possibleCharsArray = possibleChars.ToCharArray(); // optimized (precalculated) count public static int possibleCharsAvailable = possibleChars.Length; // shared randomization thingy public static Random random = new Random(); // http://stackoverflow.com/a/1344242/1037948 public string LinqIsTheNewBlack(int num) { return new string( Enumerable.Repeat(possibleCharsArray, num) .Select(s => s[random.Next(s.Length)]) .ToArray()); } // http://stackoverflow.com/a/1344258/1037948 public string ForLoop(int num) { var result = new char[num]; while(num-- > 0) { result[num] = possibleCharsArray[random.Next(possibleCharsAvailable)]; } return new string(result); } public string ForLoopNonOptimized(int num) { var result = new char[num]; while(num-- > 0) { result[num] = possibleChars[random.Next(possibleChars.Length)]; } return new string(result); } public string Repeat(int num) { return new string(new char[num].Select(o => possibleCharsArray[random.Next(possibleCharsAvailable)]).ToArray()); } // http://stackoverflow.com/a/1518495/1037948 public string GenerateRandomString(int num) { var rBytes = new byte[num]; random.NextBytes(rBytes); var rName = new char[num]; while(num-- > 0) rName[num] = possibleCharsArray[rBytes[num] % possibleCharsAvailable]; return new string(rName); } //SecureFastRandom - or SolidSwiftRandom static string GenerateRandomString(int Length) //Configurable output string length { byte[] rBytes = new byte[Length]; char[] rName = new char[Length]; SolidSwiftRandom.GetNextBytesWithMax(rBytes, biasZone); for (var i = 0; i < Length; i++) { rName[i] = charSet[rBytes[i] % charSet.Length]; } return new string(rName); } 

risultati

Testato su LinqPad. Per la dimensione della stringa di 10, genera:

  • da Linq = chdgmevhcy [10]
  • da Loop = gtnoaryhxr [10]
  • da Select = rsndbztyby [10]
  • da GenerateRandomString = owyefjjakj [10]
  • da SecureFastRandom = VzougLYHYP [10]
  • da SecureFastRandom-NoCache = oVQXNGmO1S [10]

E i numeri delle prestazioni tendono a variare leggermente, molto occasionalmente Non NonOptimized è in realtà più veloce, ea volte ForLoop e GenerateRandomString ForLoop chi è in testa.

  • LinqIsTheNewBlack (10000x) = 96762 tick trascorsi (9.6762 ms)
  • ForLoop (10000x) = 28970 tick trascorsi (2.897 ms)
  • ForLoopNonOptimized (10000x) = 33336 tick spaziati (3.3336 ms)
  • Ripeti (10000x) = 78547 battiti trascorsi (7.8547 ms)
  • GenerateRandomString (10000x) = 27416 tick trascorsi (2.7416 ms)
  • SecureFastRandom (10000x) = 13176 battiti trascorsi (5 ms) più bassi [Macchina diversa]
  • SecureFastRandom-NoCache (10000x) = 39541 battiti trascorsi (17 ms) più bassi [Macchina diversa]

Una linea di codice Membership.GeneratePassword() fa il trucco 🙂

Ecco una demo per lo stesso.

Il codice scritto da Eric J. è piuttosto sciatto (è abbastanza chiaro che è di 6 anni fa … probabilmente non avrebbe scritto quel codice oggi), e ci sono anche alcuni problemi.

A differenza di alcune delle alternative presentate, questa è crittograficamente valida.

Falso … C’è un bias nella password (come scritto in un commento), bcdefgh è un po ‘più probabile degli altri (l’ a non è perché da GetNonZeroBytes non genera byte con valore zero, quindi il bias per l’ a è bilanciato da esso), quindi non è veramente crittografico.

Questo dovrebbe correggere tutti i problemi.

 public static string GetUniqueKey(int size = 6, string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") { using (var crypto = new RNGCryptoServiceProvider()) { var data = new byte[size]; // If chars.Length isn't a power of 2 then there is a bias if // we simply use the modulus operator. The first characters of // chars will be more probable than the last ones. // buffer used if we encounter an unusable random byte. We will // regenerate it in this buffer byte[] smallBuffer = null; // Maximum random number that can be used without introducing a // bias int maxRandom = byte.MaxValue - ((byte.MaxValue + 1) % chars.Length); crypto.GetBytes(data); var result = new char[size]; for (int i = 0; i < size; i++) { byte v = data[i]; while (v > maxRandom) { if (smallBuffer == null) { smallBuffer = new byte[1]; } crypto.GetBytes(smallBuffer); v = smallBuffer[0]; } result[i] = chars[v % chars.Length]; } return new string(result); } } 

Usiamo anche string personalizzati, ma abbiamo implementato come helper di una stringa in modo da offrire una certa flessibilità …

 public static string Random(this string chars, int length = 8) { var randomString = new StringBuilder(); var random = new Random(); for (int i = 0; i < length; i++) randomString.Append(chars[random.Next(chars.Length)]); return randomString.ToString(); } 

uso

 var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Random(); 

o

 var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".Random(16); 

Un’altra opzione potrebbe essere l’uso di Linq e l’aggregazione di caratteri casuali in un costruttore di stringhe.

 var chars = "abcdefghijklmnopqrstuvwxyz123456789".ToArray(); string pw = Enumerable.Range(0, passwordLength) .Aggregate( new StringBuilder(), (sb, n) => sb.Append((chars[random.Next(chars.Length)])), sb => sb.ToString()); 

Domanda: Perché dovrei sprecare il mio tempo usando Enumerable.Range invece di digitare "ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789" ?

 using System; using System.Collections.Generic; using System.Linq; public class Test { public static void Main() { var randomCharacters = GetRandomCharacters(8, true); Console.WriteLine(new string(randomCharacters.ToArray())); } private static List getAvailableRandomCharacters(bool includeLowerCase) { var integers = Enumerable.Empty(); integers = integers.Concat(Enumerable.Range('A', 26)); integers = integers.Concat(Enumerable.Range('0', 10)); if ( includeLowerCase ) integers = integers.Concat(Enumerable.Range('a', 26)); return integers.Select(i => (char)i).ToList(); } public static IEnumerable GetRandomCharacters(int count, bool includeLowerCase) { var characters = getAvailableRandomCharacters(includeLowerCase); var random = new Random(); var result = Enumerable.Range(0, count) .Select(_ => characters[random.Next(characters.Count)]); return result; } } 

Risposta: le stringhe magiche sono CATTIVE. Qualcuno ha notato che non c’era nessun ” I ” nella mia stringa in cima? Mia madre mi ha insegnato a non usare stringhe magiche proprio per questa ragione …

nb 1: come molti altri come @dtb ha detto, non utilizzare System.Random se hai bisogno di sicurezza crittografica …

nb 2: Questa risposta non è la più efficiente o la più breve, ma volevo che lo spazio separasse la risposta dalla domanda. Lo scopo della mia risposta è più di mettere in guardia contro le stringhe magiche che fornire una risposta innovativa di fantasia.

Orribile, lo so, ma non riuscivo a trattenermi:

namespace ConsoleApplication2 { using System; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { Random adomRng = new Random(); string rndString = string.Empty; char c; for (int i = 0; i < 8; i++) { while (!Regex.IsMatch((c=Convert.ToChar(adomRng.Next(48,128))).ToString(), "[A-Za-z0-9]")); rndString += c; } Console.WriteLine(rndString + Environment.NewLine); } } }
namespace ConsoleApplication2 { using System; using System.Text.RegularExpressions; class Program { static void Main(string[] args) { Random adomRng = new Random(); string rndString = string.Empty; char c; for (int i = 0; i < 8; i++) { while (!Regex.IsMatch((c=Convert.ToChar(adomRng.Next(48,128))).ToString(), "[A-Za-z0-9]")); rndString += c; } Console.WriteLine(rndString + Environment.NewLine); } } } 

Stavo cercando una risposta più specifica, in cui voglio controllare il formato della stringa casuale e ho trovato questo post. Ad esempio: targhe (di auto) hanno un formato specifico (per paese) e volevo creare targhe a caso.
Ho deciso di scrivere il mio metodo di estensione di Random per questo. (questo è per riutilizzare lo stesso object Random, come si potrebbe avere il doppio negli scenari multi-thread). Ho creato un gist ( https://gist.github.com/SamVanhoutte/808845ca78b9c041e928 ), ma copierò anche la class di estensione qui:

 void Main() { Random rnd = new Random(); rnd.GetString("1-###-000").Dump(); } public static class RandomExtensions { public static string GetString(this Random random, string format) { // Based on http://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings-in-c // Added logic to specify the format of the random string (# will be random string, 0 will be random numeric, other characters remain) StringBuilder result = new StringBuilder(); for(int formatIndex = 0; formatIndex < format.Length ; formatIndex++) { switch(format.ToUpper()[formatIndex]) { case '0': result.Append(getRandomNumeric(random)); break; case '#': result.Append(getRandomCharacter(random)); break; default : result.Append(format[formatIndex]); break; } } return result.ToString(); } private static char getRandomCharacter(Random random) { string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; return chars[random.Next(chars.Length)]; } private static char getRandomNumeric(Random random) { string nums = "0123456789"; return nums[random.Next(nums.Length)]; } } 

Una versione leggermente più pulita della soluzione DTB.

  var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var random = new Random(); var list = Enumerable.Repeat(0, 8).Select(x=>chars[random.Next(chars.Length)]); return string.Join("", list); 

Le tue preferenze di stile possono variare.

Il mio semplice codice di linea funziona per me 🙂

 string random = string.Join("", Guid.NewGuid().ToString("n").Take(8).Select(o => o)); Response.Write(random.ToUpper()); Response.Write(random.ToLower()); 

Per espandere su questo per qualsiasi stringa di lunghezza

  public static string RandomString(int length) { //length = length < 0 ? length * -1 : length; var str = ""; do { str += Guid.NewGuid().ToString().Replace("-", ""); } while (length > str.Length); return str.Substring(0, length); } 

Prova a combinare due parti: unica (sequenza, contatore o data) e casuale

 public class RandomStringGenerator { public static string Gen() { return ConvertToBase(DateTime.UtcNow.ToFileTimeUtc()) + GenRandomStrings(5); //keep length fixed at least of one part } private static string GenRandomStrings(int strLen) { var result = string.Empty; var Gen = new RNGCryptoServiceProvider(); var data = new byte[1]; while (result.Length < strLen) { Gen.GetNonZeroBytes(data); int code = data[0]; if (code > 48 && code < 57 || // 0-9 code > 65 && code < 90 || // AZ code > 97 && code < 122 // az ) { result += Convert.ToChar(code); } } return result; } private static string ConvertToBase(long num, int nbase = 36) { var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //if you wish make algoritm more secure - change order of letter here // check if we can convert to another base if (nbase < 2 || nbase > chars.Length) return null; int r; var newNumber = string.Empty; // in r we have the offset of the char that was converted to the new base while (num >= nbase) { r = (int) (num % nbase); newNumber = chars[r] + newNumber; num = num / nbase; } // the last number to convert newNumber = chars[(int)num] + newNumber; return newNumber; } } 

test:

 [Test] public void Generator_Should_BeUnigue1() { //Given var loop = Enumerable.Range(0, 1000); //When var str = loop.Select(x=> RandomStringGenerator.Gen()); //Then var distinct = str.Distinct(); Assert.AreEqual(loop.Count(),distinct.Count()); // Or Assert.IsTrue(distinct.Count() < 0.95 * loop.Count()) } 
  public static string RandomString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var random = new Random(); return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); } 

After reviewing the other answers and considering CodeInChaos’ comments, along with CodeInChaos still biased (although less) answer, I thought a final ultimate cut and paste solution was needed. So while updating my answer I decided to go all out.

For an up to date version of this code, please visit the new Hg repository on Bitbucket: https://bitbucket.org/merarischroeder/secureswiftrandom . I recommend you copy and paste the code from: https://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdf0ffc7496ea/Code/Alivate.SolidSwiftRandom/SolidSwiftRandom.cs?at=default&fileviewer=file-view-default (make sure you click the Raw button to make it easier to copy and make sure you have the latest version, I think this link goes to a specific version of the code, not the latest).

Updated notes:

  1. Relating to some other answers – If you know the length of the output, you don’t need a StringBuilder, and when using ToCharArray, this creates and fills the array (you don’t need to create an empty array first)
  2. Relating to some other answers – You should use NextBytes, rather than getting one at a time for performance
  3. Technically you could pin the byte array for faster access.. it’s usually worth it when your iterating more than 6-8 times over a byte array. (Not done here)
  4. Use of RNGCryptoServiceProvider for best randomness
  5. Use of caching of a 1MB buffer of random data – benchmarking shows cached single bytes access speed is ~1000x faster – taking 9ms over 1MB vs 989ms for uncached.
  6. Optimised rejection of bias zone within my new class.

End solution to question:

 static char[] charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray(); static int byteSize = 256; //Labelling convenience static int biasZone = byteSize - (byteSize % charSet.Length); public string GenerateRandomString(int Length) //Configurable output string length { byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible char[] rName = new char[Length]; SecureFastRandom.GetNextBytesMax(rBytes, biasZone); for (var i = 0; i < Length; i++) { rName[i] = charSet[rBytes[i] % charSet.Length]; } return new string(rName); } 

But you need my new (untested) class:

 ///  /// My benchmarking showed that for RNGCryptoServiceProvider: /// 1. There is negligable benefit of sharing RNGCryptoServiceProvider object reference /// 2. Initial GetBytes takes 2ms, and an initial read of 1MB takes 3ms (starting to rise, but still negligable) /// 2. Cached is ~1000x faster for single byte at a time - taking 9ms over 1MB vs 989ms for uncached ///  class SecureFastRandom { static byte[] byteCache = new byte[1000000]; //My benchmark showed that an initial read takes 2ms, and an initial read of this size takes 3ms (starting to raise) static int lastPosition = 0; static int remaining = 0; ///  /// Static direct uncached access to the RNGCryptoServiceProvider GetBytes function ///  ///  public static void DirectGetBytes(byte[] buffer) { using (var r = new RNGCryptoServiceProvider()) { r.GetBytes(buffer); } } ///  /// Main expected method to be called by user. Underlying random data is cached from RNGCryptoServiceProvider for best performance ///  ///  public static void GetBytes(byte[] buffer) { if (buffer.Length > byteCache.Length) { DirectGetBytes(buffer); return; } lock (byteCache) { if (buffer.Length > remaining) { DirectGetBytes(byteCache); lastPosition = 0; remaining = byteCache.Length; } Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length); lastPosition += buffer.Length; remaining -= buffer.Length; } } ///  /// Return a single byte from the cache of random data. ///  ///  public static byte GetByte() { lock (byteCache) { return UnsafeGetByte(); } } ///  /// Shared with public GetByte and GetBytesWithMax, and not locked to reduce lock/unlocking in loops. Must be called within lock of byteCache. ///  ///  static byte UnsafeGetByte() { if (1 > remaining) { DirectGetBytes(byteCache); lastPosition = 0; remaining = byteCache.Length; } lastPosition++; remaining--; return byteCache[lastPosition - 1]; } ///  /// Rejects bytes which are equal to or greater than max. This is useful for ensuring there is no bias when you are modulating with a non power of 2 number. ///  ///  ///  public static void GetBytesWithMax(byte[] buffer, byte max) { if (buffer.Length > byteCache.Length / 2) //No point caching for larger sizes { DirectGetBytes(buffer); lock (byteCache) { UnsafeCheckBytesMax(buffer, max); } } else { lock (byteCache) { if (buffer.Length > remaining) //Recache if not enough remaining, discarding remaining - too much work to join two blocks DirectGetBytes(byteCache); Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length); lastPosition += buffer.Length; remaining -= buffer.Length; UnsafeCheckBytesMax(buffer, max); } } } ///  /// Checks buffer for bytes equal and above max. Must be called within lock of byteCache. ///  ///  ///  static void UnsafeCheckBytesMax(byte[] buffer, byte max) { for (int i = 0; i < buffer.Length; i++) { while (buffer[i] >= max) buffer[i] = UnsafeGetByte(); //Replace all bytes which are equal or above max } } } 

For history - my older solution for this answer, used Random object:

  private static char[] charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray(); static rGen = new Random(); //Must share, because the clock seed only has Ticks (~10ms) resolution, yet lock has only 20-50ns delay. static int byteSize = 256; //Labelling convenience static int biasZone = byteSize - (byteSize % charSet.Length); static bool SlightlyMoreSecurityNeeded = true; //Configuration - needs to be true, if more security is desired and if charSet.Length is not divisible by 2^X. public string GenerateRandomString(int Length) //Configurable output string length { byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible char[] rName = new char[Length]; lock (rGen) //~20-50ns { rGen.NextBytes(rBytes); for (int i = 0; i < Length; i++) { while (SlightlyMoreSecurityNeeded && rBytes[i] >= biasZone) //Secure against 1/5 increased bias of index[0-7] values against others. Note: Must exclude where it == biasZone (that is >=), otherwise there's still a bias on index 0. rBytes[i] = rGen.NextByte(); rName[i] = charSet[rBytes[i] % charSet.Length]; } } return new string(rName); } 

Performance:

  1. SecureFastRandom - First single run = ~9-33ms . Imperceptible. Ongoing : 5ms (sometimes it goes up to 13ms) over 10,000 iterations, With a single average iteration= 1.5 microseconds. . Note: Requires generally 2, but occasionally up to 8 cache refreshes - depends on how many single bytes exceed the bias zone
  2. Random - First single run = ~0-1ms . Imperceptible. Ongoing : 5ms over 10,000 iterations. With a single average iteration= .5 microseconds. . About the same speed.

Now in one-liner flavour.

 private string RandomName { get { return new string( Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13) .Select(s => { var cryptoResult = new byte[4]; new RNGCryptoServiceProvider().GetBytes(cryptoResult); return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)]; }) .ToArray()); } } 

A solution without using Random :

 var chars = Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 8); var randomStr = new string(chars.SelectMany(str => str) .OrderBy(c => Guid.NewGuid()) .Take(8).ToArray()); 

Here is a variant of Eric J’s solution, ie cryptographically sound, for WinRT (Windows Store App):

 public static string GenerateRandomString(int length) { var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; var result = new StringBuilder(length); for (int i = 0; i < length; ++i) { result.Append(CryptographicBuffer.GenerateRandomNumber() % chars.Length); } return result.ToString(); } 

If performance matters (especially when length is high):

 public static string GenerateRandomString(int length) { var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; var result = new System.Text.StringBuilder(length); var bytes = CryptographicBuffer.GenerateRandom((uint)length * 4).ToArray(); for (int i = 0; i < bytes.Length; i += 4) { result.Append(BitConverter.ToUInt32(bytes, i) % chars.Length); } return result.ToString(); } 

I know this one is not the best way. But you can try this.

 string str = Path.GetRandomFileName(); //This method returns a random file name of 11 characters str = str.Replace(".",""); Console.WriteLine("Random string: " + str); 

I don’t know how cryptographically sound this is, but it’s more readable and concise than the more intricate solutions by far (imo), and it should be more “random” than System.Random -based solutions.

 return alphabet .OrderBy(c => Guid.NewGuid()) .Take(strLength) .Aggregate( new StringBuilder(), (builder, c) => builder.Append(c)) .ToString(); 

I can’t decide if I think this version or the next one is “prettier”, but they give the exact same results:

 return new string(alphabet .OrderBy(o => Guid.NewGuid()) .Take(strLength) .ToArray()); 

Granted, it isn’t optimized for speed, so if it’s mission critical to generate millions of random strings every second, try another one!

NOTE: This solution doesn’t allow for repetitions of symbols in the alphabet, and the alphabet MUST be of equal or greater size than the output string, making this approach less desirable in some circumstances, it all depends on your use-case.

If your values are not completely random, but in fact may depend on something – you may compute an md5 or sha1 hash of that ‘somwthing’ and then truncate it to whatever length you want.

Also you may generate and truncate a guid.

 public static class StringHelper { private static readonly Random random = new Random(); private const int randomSymbolsDefaultCount = 8; private const string availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; private static int randomSymbolsIndex = 0; public static string GetRandomSymbols() { return GetRandomSymbols(randomSymbolsDefaultCount); } public static string GetRandomSymbols(int count) { var index = randomSymbolsIndex; var result = new string( Enumerable.Repeat(availableChars, count) .Select(s => { index += random.Next(s.Length); if (index >= s.Length) index -= s.Length; return s[index]; }) .ToArray()); randomSymbolsIndex = index; return result; } } 

Here is a mechanism to generate a random alpha-numeric string (I use this to generate passwords and test data) without defining the alphabet and numbers,

CleanupBase64 will remove necessary parts in the string and keep adding random alpha-numeric letters recursively.

  public static string GenerateRandomString(int length) { var numArray = new byte[length]; new RNGCryptoServiceProvider().GetBytes(numArray); return CleanUpBase64String(Convert.ToBase64String(numArray), length); } private static string CleanUpBase64String(string input, int maxLength) { input = input.Replace("-", ""); input = input.Replace("=", ""); input = input.Replace("/", ""); input = input.Replace("+", ""); input = input.Replace(" ", ""); while (input.Length < maxLength) input = input + GenerateRandomString(maxLength); return input.Length <= maxLength ? input.ToUpper() : //In my case I want capital letters input.ToUpper().Substring(0, maxLength); } 

Very simple solution. It uses ASCII values and just generates “random” characters in between them.

 public static class UsernameTools { public static string GenerateRandomUsername(int length = 10) { Random random = new Random(); StringBuilder sbuilder = new StringBuilder(); for (int x = 0; x < length; ++x) { sbuilder.Append((char)random.Next(33, 126)); } return sbuilder.ToString(); } } 

You just use the assembly SRVTextToImage . And write below code to generate random string.

 CaptchaRandomImage c1 = new CaptchaRandomImage(); string text = c1.GetRandomString(8); 

Mostly it is used to implement the Captcha. But in your case it also works. Spero che sia d’aiuto.