返回相同字符串的随机字符串生成器[重复]
Posted
技术标签:
【中文标题】返回相同字符串的随机字符串生成器[重复]【英文标题】:Random String Generator Returning Same String [duplicate] 【发布时间】:2010-11-10 11:37:51 【问题描述】:我开发了一个随机字符串生成器,但它的行为并不像我希望的那样。我的目标是能够运行两次并生成两个不同的四字符随机字符串。但是,它只是两次生成一个四字符的随机字符串。
这是代码及其输出示例:
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
如何确保两个明显随机的字符串?
【问题讨论】:
***.com/questions/4616685/… 性能良好 请注意,即使是两个完全随机的字符串也不能保证是唯一的。对于长字符串(120 多位),它们极有可能是唯一的,但对于像这样的短字符串,冲突很常见。 旧线程但是...如果适合,您可以生成 GUID 并将其转换为文本。 【参考方案1】:一个使用Path.GetRandomFileName()
的非常简单的实现:
using System.IO;
public static string RandomStr()
string rStr = Path.GetRandomFileName();
rStr = rStr.Replace(".", ""); // For Removing the .
return rStr;
现在只需拨打RandomStr()
。
【讨论】:
不错!当您在 .Net 框架中找到像 GetRandomFileName 这样的小宝石时,您会喜欢它 使用你的稍作修改。 guid = Guid.NewGuid(); mystring = guid.ToString(); mystring = mystring.Replace("-", ""); mystring = mystring.Substring(0, 8); @AndersFjeldstad 同意,我做了一个循环,它在大约 130,000 次迭代后发生碰撞。即使有 1,785,793,904,896 种组合。 这会在磁盘上创建文件。来自 MSDN:如果 GetTempFileName 方法用于创建超过 65535 个文件而不删除以前的临时文件,它将引发 IOException。如果没有唯一的临时文件名可用,GetTempFileName 方法将引发 IOException。要解决此错误,请删除所有不需要的临时文件。 @bugnuker "GetRandomFileName 方法返回一个加密的强随机字符串,可用作文件夹名称或文件名。与 GetTempFileName 不同,GetRandomFileName 不会创建文件。当您的安全性文件系统是最重要的,应该使用此方法而不是 GetTempFileName。”我们谈论的是 GetRandomFileName() 而不是 GetTempFileName()。【参考方案2】:还有另一个版本:我在测试中使用这种方法生成随机伪股票代码:
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)];
【讨论】:
【参考方案3】:这是我的解决方案:
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;
【讨论】:
【参考方案4】:另一个样本(在 vs2013 中测试):
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);
我自己实现的。
【讨论】:
【参考方案5】:如果您可以访问与 Intel Secure Key 兼容的 CPU,则可以使用以下库生成真正的随机数和字符串:https://github.com/JebteK/RdRand 和 https://www.rdrand.com/
只需从here 下载最新版本,包括 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
如果您没有兼容的 CPU 来执行代码,只需使用 rdrand.com 上的 RESTful 服务即可。使用您的项目中包含的 RdRandom 包装器库,您只需执行此操作(注册时您将获得 1000 次免费通话):
string ret = Randomizer.GenerateKey(<length>, "<key>");
您还可以生成随机字节数组和无符号整数,如下所示:
uint ret = Randomizer.GenerateUInt("<key>");
byte[] ret = Randomizer.GenerateBytes(<length>, "<key>");
【讨论】:
【参考方案6】:此解决方案是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); // "0LZnEJ_-"
random.NextString(); // "kFmeget80LZnEJ_-"
实施
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);
【讨论】:
您从整个 ascii 集中提取,包括不可打印的字符? 我添加了一个仅用于可打印符号的范围。您需要注释一行并取消注释另一行。谢谢。【参考方案7】:对于随机字符串生成器:
#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
【讨论】:
【参考方案8】:您好您可以使用 MMLib.RapidPrototyping nuget 包中的 WordGenerator 或 LoremIpsumGenerator。
using MMLib.RapidPrototyping.Generators;
public void WordGeneratorExample()
WordGenerator generator = new WordGenerator();
var randomWord = generator.Next();
Console.WriteLine(randomWord);
Nuget siteCodeplex project site
【讨论】:
【参考方案9】:在我的情况下,密码必须包含:
至少一个小写字母。 至少一个大写字母。 至少一位小数。 至少有一个特殊字符。这是我的代码:
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;
【讨论】:
【参考方案10】:我想可能这也是可以接受和简单的。
Guid.NewGuid().ToString()
【讨论】:
GUID 不能保证是随机的,因此您不应将它们用作 PRNG。 Windows 上的当前实现是随机的,但在旧版本上它是基于 MAC 地址和时间的。谁知道未来的版本会使用什么。 我不这么认为。现在很多人使用 GUID 作为主键,是的,GUID 可能会发生冲突,但写出的2^128
大约是:34,028,236,692,093,846,346,337,460,743,177,000,000
。从统计上看,如果你每秒计算 1000 个 GUID,仍然需要数万亿年才能得到一个副本。顺便说一句,使用 guid 就是这么简单,我不认为这是一个坏主意。
GUID 的意义在于它是唯一的,而不是随机的。如果您将其用作唯一 ID,我不会抱怨,但您将其作为随机字符串出售,目前是这样,但不能保证如此。 (并且感谢生日问题,您只需要大约 2^61 的值即可达到重复而不是 2^122,因此您的“万亿年”实际上只有大约 7500 万年)
这样可以生成随机字符串,仅此而已。虽然不能生成相同的序列。
它恰好在当前实现中生成了一个大部分随机字符串(其中部分不是随机的)。不保证是随机的,过去的实现不是随机的,未来的实现也可能不是随机的。【参考方案11】:
一个 LINQ 单行代码(假设为 private static Random Random
)...
public static string RandomString(int length)
return new string(Enumerable.Range(0, length).Select(_ => (char)Random.Next('a', 'z')).ToArray());
【讨论】:
【参考方案12】:我的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);
【讨论】:
【参考方案13】:这里还有一个选项:
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());
【讨论】:
【参考方案14】:实际上,一个好的解决方案是为随机数生成器提供一个线程安全且不使用锁的静态方法。
这样,同时访问您的网络应用程序的多个用户不会得到相同的随机字符串。
这里有 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(),而您的方法可以保持静态。
【讨论】:
【参考方案15】:另一个版本的字符串生成器。简单,没有花哨的数学和魔术数字。但是有一些指定允许字符的魔术字符串。
更新: 我将生成器设为静态,因此在多次调用时它不会返回相同的字符串。然而,这段代码不 线程安全,而且绝对不 加密安全。
密码生成应使用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();
【讨论】:
如果你多次调用它会生成相同的字符串.. 感谢@stian.net,我将生成器设为静态。【参考方案16】: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);
【讨论】:
【参考方案17】:我发现这更有帮助,因为它是一个扩展,它允许您选择代码的来源。
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 ;
希望这会有所帮助。
【讨论】:
【参考方案18】:这是我对当前接受的答案的修改,我认为它更快更短:
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)
可以更改为任何范围的 Unicode 字符。
【讨论】:
psst...您实际上没有回答 OP 遇到的 问题... @Andrew 这实际上解决了问题,注意这也是我对接受的答案进行的优化。 您的代码可以。不过,您的描述没有提及。至于它是一种优化;在同意该声明之前,我想看看一些基准;发生了一些事情,你(显然)不知道。就像隐式转换一样。另外,您可能错过了最大的性能提升 - 为 StringBuilder 指定起始大小。 (恕我直言) @Andrew 我将修改我的答案以反映这一点,但是使用.NET 提供的方法生成均匀分布,而不是涉及乘法和地板操作的自定义方法,必须更快。 【参考方案19】:最好的解决方案是使用随机数生成器和base64转换
public string GenRandString(int length)
byte[] randBuffer = new byte[length];
RandomNumberGenerator.Create().GetBytes(randBuffer);
return System.Convert.ToBase64String(randBuffer).Remove(length);
【讨论】:
注意结果可以包含/
和+
。
是的。但是我更喜欢这个而不是 Membership.GeneratePassword()
return System.Convert.ToBase64String(randBuffer).Replace("/", "").Replace("+", "").Replace("=", "").Remove(长度);【参考方案20】:
还有一个基于 GUID 的想法。我已将它用于Visual Studio performance test,以生成仅包含字母数字字符的随机字符串。
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);
【讨论】:
【参考方案21】:只要您使用的是 Asp.Net 2.0 或更高版本,您还可以使用库调用-
System.Web.Security.Membership.GeneratePassword
,但它会包含特殊字符。
要获得至少 0 个特殊字符的 4 个随机字符-
Membership.GeneratePassword(4, 0)
【讨论】:
请注意,在 4.0 中,第二个整数参数表示要使用的 最小 个非AlphaNumericCharacters。所以Membership.GeneratePassword(10, 0);
不会像你想象的那样工作,它仍然会放入大量非字母数字字符,例如:z9sge)?pmV
我能想到的不想在其他方法上使用它的唯一原因是你必须经历删除特殊字符的麻烦......假设你需要我不这样做't
感谢 keithl8041,更新了答案以反映这一点。
对我来说,只要您有权获得会员资格,这就是正确的答案。我的意思是,为什么要重新发明热水?【参考方案22】:
我创建了这个方法。
效果很好。
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;
【讨论】:
再次表明安全性难以测试。虽然它“效果很好”,但它并不安全。使用安全的 PRNG 生成密码。【参考方案23】:我添加了使用 Ranvir 解决方案选择长度的选项
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);
【讨论】:
【参考方案24】:仅适用于路过的人以及在一行代码中包含随机字符串的内容
int yourRandomStringLength = 12; //maximum: 32
Guid.NewGuid().ToString("N").Substring(0, yourRandomStringLength);
PS:请记住,yourRandomStringLength
不能超过 32,因为 Guid
的最大长度为 32。
【讨论】:
我不确定这一定是随机的。 GUID 被设计为唯一的,而不是随机的,因此字符串中的前 N 个字符可能相同(取决于 GUID 生成器)。 我只需要一个 5 个字符的临时密码来散列。太好了,谢谢。【参考方案25】:结合“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);
【讨论】:
C# 没有默认参数 AFAIK。 @xiaomao 你说的不对。我一直在使用它们。顺便说一下,它们被称为“可选参数”。 @Andrew OK,这是来自 MSDN 的新增内容:“Visual C# 2010 引入了命名参数和可选参数”。 @xiaomao 我不会打电话给超过 3 年,而之前的一个完整版本是“新增”。到去年 9 月发布此答案时,它已经是一个成熟的功能。【参考方案26】:如果您想为强密码生成一串数字和字符。
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();
【讨论】:
请注意,Random 类的实例成员未记录为线程安全的,因此如果同时从多个线程调用此方法(如果您正在制作 Web 应用程序,很有可能,例如)那么这段代码的行为将是未定义的。您要么需要对随机数使用锁,要么在每个线程中使用。 @GregBeech 真的吗?再次?很无聊?【参考方案27】:您正在方法中实例化 Random
对象。
Random
对象是seeded from the system clock,这意味着如果你快速连续多次调用你的方法,它每次都会使用相同的种子,这意味着它会生成相同的随机数序列,这意味着你会得到相同的字符串。
要解决此问题,请将您的 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);
【讨论】:
或者将其设为静态并在类内部。 另外,我喜欢将这种方法作为 Random 的扩展方法。 请注意,Random 类的实例成员未记录为线程安全的,因此如果同时从多个线程调用此方法(如果您正在制作 Web 应用程序,很有可能,例如)那么这段代码的行为将是未定义的。您要么需要对随机数使用锁,要么在每个线程中使用。【参考方案28】:您正在方法中创建 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;
(修改后的代码)
【讨论】:
请注意Random
类的实例成员未记录为线程安全的,因此如果同时从多个线程调用此方法(如果您正在制作网络,很有可能app,例如),那么这段代码的行为将是未定义的。您要么需要对随机数使用锁,要么在每个线程中使用。
是的,随机不是线程安全的,会在 asp.net 网站上引起很多问题
另外,您可以使用ch = (char)random.Next('A','Z');
获得一个随机大写字母,这比原始帖子中无法读取的行ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
简单得多。然后如果你想切换成小写,你可以轻松切换到(char)random.Next('a','z');
@NickFreeman:记住the upper bound is exclusive,所以ch = (char)random.Next('A','Z');
永远不会返回'Z'
。所以你需要ch = (char)random.Next('A', 'Z' + 1);
来包含'Z'
。
我实际上使用new Random(Guid.NewGuid().GetHashCode());
作为种子,而不是依赖DateTime
。【参考方案29】:
这是因为 Random 的每个新实例都在快速调用时生成相同的数字。 不要继续创建新实例,只需调用 next() 并在方法之外声明您的随机类。
【讨论】:
【参考方案30】:您应该在构造函数中启动一个类级别的 Random 对象,并在每次调用时重复使用(这会延续相同的伪随机数序列)。无参数构造函数已在内部使用 Environment.TickCount 为生成器播种。
【讨论】:
以上是关于返回相同字符串的随机字符串生成器[重复]的主要内容,如果未能解决你的问题,请参考以下文章