2013-04-09 51 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