2013-04-06 72 views
-1

是的,我搜索了这种情况,但无法真正涉及的人来此......(别来砸我吧...)随机对象的引用

public Random Randomizer; 

string[] Monsters = { "Rat", "Giant Rat", "Skeleton", "Infected" }; 

public string DisplayKilled() 
{ 
    if (PlayerOne.Level <= 5) 
    { 
     string randomMonster = Monsters[Randomizer.Next(1,2)]; // <= problemo 

错误,我在得到“string randomMonster = Monsters [Randomizer.Next(1,2)];” :未将对象引用设置为对象的实例。我能做些什么来解决这个问题?

回答

6

您可以初始化您的变量。目前,你从来没有把它设置为一个值。它宣布这里:

public Random Randomizer; 

...但是你从来没有给它的值,所以将有null的默认值,这会导致异常时,当你抛出取消对它的引用。值得了解的是,这与没有关系,因为它与随机性有关......这与任何参考类型变量(例如,一个string或一个Stream

可以只需使用:

private readonly Random randomizer = new Random(); 

...但也有其他缺点这一点。 (请注意,我已将其设置为私密且只读的 - 您应该几乎在任何地方避免使用公共区域,并且只能在只读对象的整个生命周期内改变其值)。

就缺点而言,有两个担心:

  • 如果您创建的Random多个实例的时间非常短的空间参数的构造函数,其中许多可以共享相同的种子,这意味着它们会产生相同的随机数字。
  • Random不是线程安全的 - 如果您在没有任何锁定的情况下使用多个线程中的单个实例,则可以轻松进入每次仅返回0的状态。

这两个特别讨厌在一起...如果不是线程安全方面,只声明一个静态字段并对所有内容使用相同的实例是相当合理的。但是,如果你涉及多个线程,那不起作用。同样,如果共享种子不是问题,那么每次只需要创建一个就可以了。

我有一个page on randomness in .NET,它会介绍更多细节并提出一些解决方法。

+1

Oh,Derp user2129296 = new Derp(); – user2129296 2013-04-06 22:14:28

+0

我的猜测是他创建了多个实例(共享种子),但只使用一个线程,在这种情况下,你应该说他应该使'randomizer'静态,如'private static readonly Random randomizer = new随机();'。我也认为他应该把它变成静态的。 (只有它是多线程的,并且如果每个线程都有其他线程没有使用的自己的实例,并且如果多个实例没有短时间创建,那么_then_最好保持该字段不是静态的。) – 2013-04-06 22:45:51

+0

@JeppeStigNielsen:我认为把它变成静态是一件有风险的事情 - 现在使用单线程太容易了,但后来使用多线程并忘记了你有这个定时炸弹在等待...... – 2013-04-07 08:06:58

1
public Random Randomizer = new Random();