2013-04-06 58 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();