我是初学程序员,需要一些帮助。在我的程序开始时,创建了5个兔子(对象类型Bunny)。它看起来像这样:
List<Bunny> bunnies = new List<Bunny>();
Bunny newBunny;
for(int i = 0; i < 5; i++)
{
newBunny = new Bunny();
bunnies.Add(newBunny);
}
我的问题是newBunny的构建耗时太长,程序继续使用for循环。这导致列表只有第一个构造的newBunny和它的副本。运行代码打印出以下信息:
名字 - 凯特,性别 - 男性,颜色白,年龄0,放射性假
名字 - 凯特,性别 - 男性,颜色白,年龄0,放射性假
名字 - 凯特,性别 - 男性,颜色白,年龄0,放射性假
名字 - 凯特,性别 - 男性,颜色白,年龄0,放射性假
名字 - 凯特,性别 - 男性,颜色白,年龄0,放射性假
结构如下:
public Bunny()
{
Random randNum = new Random ();
int namesCount = Enum.GetNames(typeof(BunnyName)).Length;
Name=((BunnyName)(randNum. Next(0, namesCount)));
int genderCount = Enum.GetNames(typeof(BunnyGender)).Length;
Gender=((BunnyGender)(randNum. Next(0, genderCount)));
int colorCount = Enum.GetNames(typeof(BunnyColor)).Length;
Color=((BunnyColor)(randNum. Next(0, colorCount)));
Age=-1;
if(randNum. Next(1,101)<2)
Radioactive = true;
else
Radioactive =false;
}
我希望程序停止,直到newBunny的构造结束,然后才将它添加到列表中:
List<Bunny> bunnies = new List<Bunny>();
Bunny newBunny;
for(int i = 0; i < 5; i++)
{
//stop until next line finishes
newBunny = new Bunny();
//continue
bunnies.Add(newBunny);
}
聚苯乙烯。如果我调试程序它运行得很好,就像我想要的那样(新的兔子不是&#39;重复&#39;) 此外,如果我在for循环的末尾添加一个messageBox,一切都很好。 这就是为什么我认为它可能需要暂停
for(int i = 0; i < 5; i++)
{
//stop until next line finishes
newBunny = new Bunny();
//continue
bunnies.Add(newBunny);
MessageBox.Show("test");
}
希望你理解我的问题,谢谢。
答案 0 :(得分:1)
您的程序执行完全同步,因此实际上列表中有5个不同的Bunny实例。 如果你不相信我改变了Bunny的构造函数并为其添加了一个整数。在构造函数中,将此整数分配给Bunny的实例变量,如下所示:
public class Bunny{
private int _instanceId;
public Bunny(int instanceId){
_instanceId = instanceId;
}
}
循环中的执行此操作:
newBunny = new Bunny(i);
现在使用调试器来逐步执行代码。希望视觉工作室。在add语句上放置一个断点,并将光标导航/悬停在bunnies变量上以查看其中的内容。您甚至可以检查不同的实例,您将看到instanceid是不同的。 您的代码只创建了5个不同的Bunny实例,但由于构造函数相同,最终会得到5个看起来完全相同的实例。
要获得真正随机的值,请在构造函数中执行此操作:
static Random randNum = new Random ();
答案 1 :(得分:1)
Random in a loop?它们可能是不同的对象,但所有随机数都是相同的。
这是因为Random
的构造函数在没有参数时使用系统时钟的种子。因此,如果您像这样快速新建它们,它们最终都会相同,并且在您拨打Next
时会给出相同的值。
将一个Random传递给所有构造函数并使用它更好。
List<Bunny> bunnies = new List<Bunny>();
Random random = new Random();
for(int i = 0; i < 5; i++)
{
bunnies.Add(new Bunny(random));
}
您也不需要变量来将兔子置于不必要的高scope。如果你只在for循环中使用某些东西,它就不需要存在于它之外。
有人建议在Bunny类中使用静态随机数,但我建议反对它。将事物注入实例有很多好处(特别是在多线程时),但在你的情况下,优点是可测试性。
我已经将下面的一个类作为您可以用来测试Bunny构造函数的示例,您可以控制生成的Bunny,然后验证发生的事情是否正确:
class MyRandomIsAlwaysN : Random
{
private readonly int nextValue;
public MyRandomIsAlwaysN(int n){
this.nextValue = n;
}
public override int Next(int x, int y){
return this.nextValue
}
}
答案 2 :(得分:1)
您遇到的问题是使用Random。
见这里:C# Random Numbers aren't being "random"
我建议你在bunny之外创建一个Random类,然后将它传递给构造函数。
即
List<Bunny> bunnies = new List<Bunny>();
Bunny newBunny;
Random randomGenerator = new Random();
for(int i = 0; i < 5; i++)
{
newBunny = new Bunny(randomGenerator);
bunnies.Add(newBunny);
}