2015-05-02 30 views
1

在某些時候,我想隨機化,如果一個數組在創建時會被倒置。循環參數是否執行每次迭代?

的第一件事情我想是這樣的:

bool reverse = Random.value > 0.5f; 
for (
     int i = reverse ? steps - 1 : 0; 
     reverse ? i >= 0 : i < steps; 
     i += reverse ? -1 : +1 
    ) { 
    rotateScript.angles.Add(angleRange[0] + stepAdder * i); 
} 

後來我意識到,儘管採取更多的線,兩條用於內部的循環的if/else將更具可讀性。

但問題依然存在:這些三元條件是每次迭代執行還是隻執行一次?

回答

1

正如@Dai指出的那樣,第二個和第三個語句必須在每次迭代結束時進行評估。

此行爲在C#語言規範的§8.8.3中詳細說明。意譯,它說大約

for (initialiser; condition; iterator;) { ... } 

語句:

  • 如果爲初始值設定存在,則變量初始值設定或聲明表達式是:

    for語句甲如下執行按照它們寫入的順序執行。此步驟僅執行一次。

  • 如果存在for-condition,則會進行評估。
  • 如果for-condition不存在或評估結果爲真,則控制權將轉移到嵌入式聲明中。當和如果控制到達嵌入語句的終點時,for-iterator的表達式將按順序進行評估,然後執行另一次迭代,從上面的步驟中的for-condition的求值開始。
  • 如果存在for-condition並且評估結果爲false,則將控制權轉移到for語句的結束點。

與您的代碼

for (
    int i = reverse ? steps - 1 : 0; 
    reverse ? i >= 0 : i < steps; 
    i += reverse ? -1 : +1 
) { 
    rotateScript.angles.Add(angleRange[0] + stepAdder * i); 
} 

你有幾個選項,使在達到迭代不必要的三元運算符。

您提到使用if/else與兩個for循環,但我建議您不要這樣做,因爲它會重複代碼,從而妨礙其可維護性和可讀性。


選項1:使用標準for循環:

你可以把邏輯到代碼循環,即

for (i = 0; i < steps; i += 1) 
{ 
    int multiplier = reverse ? steps - 1 - i: i; 
    rotateScript.angles.Add(angleRange[0] + stepAdder * multiplier); 
} 

選項2:移動三元邏輯輸出:

計算極限和增量第一,即

int start = reverse ? steps - 1 : 0; 
int increment = reverse ? -1 : +1; 
int limit = reverse ? -1 : steps; 

for (int i = start; i != limit; i += increment;) 
{ 
    rotateScript.angles.Add(angleRange[0] + stepAdder * i); 
} 

我寧願選擇1,因爲我認爲大多數人覺得簡單for循環更容易理解。

+0

我的確喜歡選項1,確實比兩個循環的if/else更好。真的很好的答案,謝謝! –

+0

沒問題 - 很高興有幫助!另外,非常感謝接受我的答案! :) –

4

正確,for語句的第二個和第三個組件在每次迭代中進行評估。

此:

for(x; y; z) a; 

等同於:

x; 
while(y) { a; z; } 

z所以y將被評估1周更多的時間。

+0

謝謝。我想也許編譯器會在參數裏面做一些工作,但是現在我發現它無法工作,因爲我顯然可以在循環範圍內改變「反向」布爾值的值。 –