2013-04-09 64 views
2

有時,我遇到了像這樣的循環,我不確定它應該如何構造,以避免代碼重複並使其更具可讀性。我應該如何構建這個循環?

請注意,雖然在本例中我使用C#編寫並使用Unity3d引擎,但這個問題是關於一般循環的,並且這裏沒有關於C#/ Unity3d的具體內容,或者對我而言似乎如此。

// ... 

    Vector3 rayPosition = transform.position; 
    Vector3 rayDirection = transform.forward; 

    RaycastHit hit; 

    Vector3 rayFinish = rayPosition + rayDirection * rangeLeft; // This line repeats... 

    while (Physics.Linecast (rayPosition, rayFinish, out hit)) { 

     rangeLeft -= hit.distance; 

     rayPosition = hit.point; 
     rayDirection = Vector3.Reflect(rayDirection, hit.normal); 

     rayFinish = rayPosition + rayDirection * rangeLeft; // ...here. 

    } 

    // ... 

(當然,這個代碼重複是微不足道的小事,但它只是一個例子。)

這是不可能while循環,因爲病情需要,使之成爲做...在第一次運行循環之前檢查。編寫這樣的代碼的最佳方式是什麼?

回答

0

do-while循環有點棘手,因爲測試是一種需要在循環體之前調用的方法。下面的代碼消除了重複,但我不確定它對可讀性有多大幫助。

while (true) { 
    Vector3 rayFinish = rayPosition + rayDirection * rangeLeft; 

    if (!Physics.Linecast (rayPosition, rayFinish, out hit)) 
     break; 

    rangeLeft -= hit.distance; 

    rayPosition = hit.point; 
    rayDirection = Vector3.Reflect(rayDirection, hit.normal); 
} 

這可能是多一點可讀性:

bool linecastGood = true; 

while (linecastGood) { 
    Vector3 rayFinish = rayPosition + rayDirection * rangeLeft; 

    linecastGood = Physics.Linecast (rayPosition, rayFinish, out hit) 

    if (linecastGood) 
    { 
    rangeLeft -= hit.distance; 
    rayPosition = hit.point; 
    rayDirection = Vector3.Reflect(rayDirection, hit.normal); 
    } 
} 
+0

其實,我收到了第一個變體,然後將其重構了這一點。 (真的)總是被認爲是不好的做法,是不是循環? 第二個避免代碼重複,但在我看來,它的可讀性較差 - 您必須至少掃描兩次代碼以瞭解它在做什麼。 – 2013-04-09 19:00:34

+0

@golergka:我同意應該避免使用(true),這就是爲什麼我認爲版本2可能更具可讀性的原因。我只是編輯它使意圖更加明確(IMO),但它仍然不是很好。根本的問題是,你希望在循環體中間使用一次調用來進行必要的計算,而且還要使用它的返回值作爲循環條件。循環條件僅在開始或結束時出現,所以除了保存該值並在while條件中使用它,或者使用它跳出循環中間外,我沒有看到任何其他選擇。或者使用轉到... – 2013-04-09 19:15:06