我有一个方法可以随机生成字母数字组合。如果我在一个循环中调用它,它将返回相同的组合,但如果我在GetVoucherNumber
上放置一个断点并逐步执行它,则每次都会生成一个不同的数字。你能解释一下为什么会发生这种情况以及如何避免它吗?
代码:
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
Console.WriteLine(GetVoucherNumber(6));
Console.ReadLine();
}
public static string GetVoucherNumber(int length)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var random = new Random();
var result = new string(
Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)])
.ToArray());
return result;
}
答案 0 :(得分:14)
您的问题是您只创建一个Random实例。默认情况下,如果您不提供种子编号,则当前时间将用作种子。但是,您的代码执行速度如此之快,以至于同一时间被用作种子(因为您的代码执行速度比时钟的最小分辨率快),因此您收到的数字是每次都一样。
添加断点时,会在程序中添加延迟,以便为种子使用不同的时间。
最好的解决方法是只创建一个Random实例。然后,每次拨打random.Next
都会生成不同的号码。例如,您可以将代码更改为:
private static Random random = new Random();
public static string GetVoucherNumber(int length)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var result = new string(
Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)])
.ToArray());
return result;
}
答案 1 :(得分:2)
<强>问题:强>
在如此连续的实例中创建随机对象,它生成相同的随机数。
如果不向随机对象提供任何种子值,则将当前DateTime用作其种子值。现在,当调用循环时,DateTime保持不变,因此当前的DateTime是 用于生成给出相同随机数的随机数。
<强>解决方案:强>
现在创建一次随机数实例,并始终调用其下一个,给出实际的随机数。
static void Main(string[] args)
{
Random random = new Random();
for (int i = 0; i < 100; i++)
Console.WriteLine(GetVoucherNumber(6, random));
Console.ReadLine();
}
public static string GetVoucherNumber(int length, Random random)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var result = new string(
Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)])
.ToArray());
return result;
}