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。现在。勾选
值作为种子值。由于您的实例将以非常快的顺序重新创建,因此该实例将以相同的节拍播种。因此是相同的随机数

证明:在代码中添加一些断点。然后你会得到真正的随机值,因为