为什么这个随机字符串生成器总是返回相同的值
本文关键字:返回 随机 字符串 为什么 | 更新日期: 2023-09-27 18:35:53
我今天遇到了一个奇怪的问题,我可以理解原因。 采用以下控制台程序。
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();
}
}
如果我在程序的 上放置一个断点并运行程序,则 s1、s2、s3 的值都相等。 现在,如果我在 s2 处放置一个断点,例如返回的值会有所不同。
似乎是某种并发问题? 这是怎么回事?
谢谢
随机数生成器实际上不是完全随机的:给定相同的种子值,多个实例将生成相同的随机序列。
不能说它比随机构造函数的 MSDN 文档更好
"默认种子值派生自系统时钟,并且具有 有限分辨率。因此,不同的随机对象是 通过调用默认构造函数紧密连续创建将 具有相同的默认种子值,因此将产生 相同的随机数集。此问题可以通过使用 单个随机对象以生成所有随机数。你也可以 通过修改系统返回的种子值来解决此问题 时钟,然后将此新种子值显式提供给 随机 (Int32) 构造函数。有关详细信息,请参阅 随机 (Int32) 构造函数。
因此,在您的情况下,您需要将 Random 实例保留为类级字段或函数参数,并且仅实例化一次。
因为您在每次调用GenerateRandomCode
时都会实例化一个新Random
,并且调用花费的时间非常短,所以所有 3 个 Random
对象最终都会使用相同的基于时间的种子,这意味着它们都将返回相同的第一个值。为 Random
对象创建一个字段,在程序开始时仅实例化一次,并GenerateRandomCode
改用该Random
实例 - 现在,当您调用 random.NextDouble()
时,您将获得不同的值。
将new Random()
呼叫拉出GenerateRandomCode
。
由于您每次都重新创建它并快速连续调用它,因此它可能获得相同的随机种子值。
您可以将其设置为静态,也可以使用依赖关系注入(将其传入)。
我相信这将解决问题。
原因:随机数实例在未给定任何种子值时DateTime.Now.Ticks
值作为种子值。由于您的实例会以非常快的连续方式重新创建,因此该实例会使用相同的刻度进行种子设定。因此相同的随机数。
证明:在代码中放置一些断点。然后你会得到真正的随机值,因为当它击中调试器时,在你按 F10 或 F11 或 F5 之前会有时间损失。导致延时。
解决方案:创建 Random 类的静态实例,并在任何需要的地方使用其 Next 函数。