C# 为什么这个随机字符串生成器总是返回相同的值
我今天遇到一个奇怪的问题,我能理解原因。以下面的控制台程序为例C# 为什么这个随机字符串生成器总是返回相同的值,c#,random,concurrency,C#,Random,Concurrency,我今天遇到一个奇怪的问题,我能理解原因。以下面的控制台程序为例 internal class Program { private static void Main(string[] args) { string s1 = GenerateRandomCode(8); string s2 = GenerateRandomCode(8); string s3 = GenerateRando
internal class Program
{
private static void Main(string[] args)
{
string s1 = GenerateRandomCode(8);
string s2 = GenerateRandomCode(8);
string s3 = GenerateRandomCode(8);
}
public static string GenerateRandomCode(int length)
{
string charPool = "ABCDEFGOPQRSTUVWXY1234567890ZabcdefghijklmHIJKLMNnopqrstuvwxyz";
StringBuilder rs = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++)
{
rs.Append(charPool[(int)(random.NextDouble() * charPool.Length)]);
}
return rs.ToString();
}
}
内部类程序
{
私有静态void Main(字符串[]args)
{
字符串s1=生成器域代码(8);
字符串s2=GeneratorDomainCode(8);
字符串s3=生成器域代码(8);
}
公共静态字符串生成器域代码(int-length)
{
字符串charPool=“abcdefgopqrstuvwxy1234567890zabcdefghijklmhijklmnnopqrstuvxyz”;
StringBuilder rs=新的StringBuilder();
随机=新随机();
for(int i=0;i
如果我在程序的末尾设置一个断点并运行程序,那么s1、s2、s3的值都是相等的。现在,如果我把一个断点放在s2,例如,返回的值将不同
好像是某种并发问题?发生什么事了
谢谢,因为您在每次调用
GenerateRandomCode
时都实例化了一个新的Random
,而且因为调用花费的时间很短,所以所有3个Random
对象都以相同的基于时间的种子结束,这意味着它们都将返回相同的第一个值。为Random
对象创建一个字段,在程序开始时仅实例化一次,并让GenerateRandomCode
使用该Random
实例-现在调用Random.NextDouble()时将得到不同的值
因为您在每次调用GeneratorDomainCode
时都实例化了一个新的Random
,而且调用花费的时间很短,所以所有3个Random
对象都以相同的基于时间的种子结束,这意味着它们都将返回相同的第一个值。为Random
对象创建一个字段,在程序开始时仅实例化一次,并让GenerateRandomCode
使用Random
的实例-现在,当调用Random.NextDouble()
拉取新的Random()时,您将得到不同的值
在GenerateRandomCode
之外调用
因为您每次都在重新创建它并快速连续调用它,所以它可能会得到相同的随机种子值
您可以将其设置为静态,或者使用依赖项注入(传入)
我相信这会解决问题。将新的Random()
调用拉到GenerateRandomCode
之外
因为您每次都在重新创建它并快速连续调用它,所以它可能会得到相同的随机种子值
您可以将其设置为静态,或者使用依赖项注入(传入)
我相信这会解决问题。随机数生成器实际上不是完全随机的:给定相同的种子值,多个实例将生成相同的随机序列 没有比随机构造函数更好的了 “默认种子值源自系统时钟,并且具有 有限分辨率。因此,不同的随机对象 通过调用默认构造函数连续创建的 具有相同的默认种子值,因此将生成 相同的随机数集。使用 生成所有随机数的单个随机对象。您还可以 通过修改系统返回的种子值来解决此问题 时钟,然后将此新种子值显式提供给 Random(Int32)构造函数。有关更多信息,请参阅Random(Int32) 构造师。”
因此,在本例中,您需要将随机实例保留为类级字段或函数参数,并仅实例化一次。随机数生成器实际上不是完全随机的:给定相同的种子值,多个实例将生成相同的随机序列 没有比随机构造函数更好的了 “默认种子值源自系统时钟,并且具有 有限分辨率。因此,不同的随机对象 通过调用默认构造函数连续创建的 具有相同的默认种子值,因此将生成 相同的随机数集。使用 生成所有随机数的单个随机对象。您还可以 通过修改系统返回的种子值来解决此问题 时钟,然后将此新种子值显式提供给 Random(Int32)构造函数。有关更多信息,请参阅Random(Int32) 构造师。”
因此,在您的情况下,您需要将随机实例保留为类级字段或函数参数,并且只实例化一次。原因:没有给定任何种子值的随机数实例将
DateTime.Now.勾选值作为种子值。由于您的实例将以非常快的顺序重新创建,因此该实例将以相同的节拍播种。因此是相同的随机数
证明:在代码中添加一些断点。然后,您将获得真正的随机值,因为当它将触发调试器时,在按F10、F11或F5之前会损失时间。导致时间流逝
解决方案:创建Random类的静态实例,并在任何需要的地方使用其下一个函数。原因:未给定任何种子值的随机数实例采用DateTime。现在。勾选值作为种子值。由于您的实例将以非常快的顺序重新创建,因此该实例将以相同的节拍播种。因此是相同的随机数
证明:在代码中添加一些断点。然后你会得到真正的随机值,因为