2015-02-08 99 views
0

我是一個初學者程序員,需要一些幫助。在我的節目開始時,創建了5個兔子(物體類型兔子)。它看起來像這樣:暫停,直到對象創建成功

List<Bunny> bunnies = new List<Bunny>(); 
Bunny newBunny; 
for(int i = 0; i < 5; i++) 
{ 
    newBunny = new Bunny(); 
    bunnies.Add(newBunny); 
} 

我的問題是newBunny的構造花費時間太長,程序繼續for-loop。這將導致清單剛纔的第一個構建newBunny和it.Running的重複的代碼打印我下面的:

名稱 - 凱特,性別男,色白,年齡0,放射性假

名稱 - 凱特,性別男,色白,年齡0,放射性假

名稱 - 凱特,性別男,色白,年齡0,放射性假

名稱-Kate,性別 - 男性,顏色 - 白色,年齡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); 
} 

Ps。如果我正在調試程序,它運行得很好,就像我希望它(新的兔子不'重複') 另外,如果我在for循環的末尾添加messageBox,一切正常。 這就是爲什麼我認爲這可能需要停止

for(int i = 0; i < 5; i++) 
{ 
    //stop until next line finishes 
    newBunny = new Bunny(); 
    //continue 
    bunnies.Add(newBunny); 
    MessageBox.Show("test"); 
} 

希望你明白我的問題,謝謝。

+11

「我的問題是newBunny的建設時間太長,程序與for循環,這將導致該列表繼續剛纔的第一個構建newBunny和它的複製品。」不,這是不正確的。目前尚不清楚爲什麼你會這麼想,但事實並非如此。請提供一個簡短但完整的程序來說明問題,我們可以幫助您診斷問題。還要注意,通過在循環內而不是外部聲明變量*,代碼會更好(IMO),一般來說,使用局部變量的最小可能範圍。 – 2015-02-08 19:48:17

+0

你是如何確定它是同一個對象的? – Tarik 2015-02-08 19:55:00

+0

如果使用在構造函數內部啓動的非阻塞線程(用於初始化對象的屬性),可能會導致此行爲,但如果您是新程序員,則不太可能會這樣做。 – Aalawlx 2015-02-08 19:57:03

回答

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循環中使用某些東西,它不需要在for循環之外。

建議在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 
    } 
} 
1

你的程序執行是完全同步的,所以實際上列表中有5個不同的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

的你的問題在於你的隨機使用。

在這裏看到:C# Random Numbers aren't being "random"

我會建議你創建兔子之外的一個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); 
}