我今天遇到一个奇怪的问题,我能理解其中的原因。采取以下控制台程序。
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处放置一个断点,例如返回的值将是不同的。
看起来像某种并发问题?发生了什么事?
由于
答案 0 :(得分:2)
随机数生成器实际上并非完全随机:给定相同的种子值,多个实例将生成相同的随机序列。
对于Random构造函数
,不能说比MSDN documentation更好“默认种子值是从系统时钟派生而来的 有限分辨率。结果,不同的Random对象就是 通过调用默认构造函数将紧密连续创建 具有相同的默认种子值,因此将产生 相同的随机数集。使用可以避免此问题 单个Random对象生成所有随机数。你也可以 通过修改系统返回的种子值来解决它 时钟然后明确地提供这个新的种子值 随机(Int32)构造函数。有关更多信息,请参阅随机(Int32) 构造函数“。
因此,在您的情况下,您需要将Random实例保持为类级别字段或函数参数,并仅将其实例化一次。
答案 1 :(得分:1)
因为您在每次调用Random
时都实例化了一个新GenerateRandomCode
,并且由于调用所花费的时间非常少,所以所有3个Random
个对象最终都使用相同的基于时间的种子,意味着他们都将返回相同的第一个值。为您的Random
对象创建一个字段,在程序开始时只对其进行一次实例化,然后让GenerateRandomCode
使用Random
的实例 - 现在您将获得不同的值致电random.NextDouble()
。
答案 2 :(得分:1)
将new Random()
电话拉出GenerateRandomCode
。
由于您每次都在重新创建并快速连续调用它,因此它可能会获得相同的随机种子值。
您可以将其设置为静态,或使用依赖注入(传入)。
我相信这样可以解决问题。
答案 3 :(得分:0)
原因:未给定任何种子值的随机数实例将DateTime.Now.Ticks
值作为种子值。由于您的实例正在以非常快的连续方式重新创建,因此实例将以相同的刻度进行播种。因此相同的随机数。
证明:在代码中添加一些断点。然后你会得到真正的随机值,因为它会打击一个调试器,在你按F10或F11或F5之前会有一段时间。造成时间流逝。
解决方案:创建一个Random类的静态实例,并根据需要使用其Next函数。