2015-05-02 2 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); 
} 

Позже я понял, несмотря на принятие более линий, два для петель внутри если/другое будет более удобным для чтения.

Но вопрос остался: будут ли эти тернарные условия выполняться каждую итерацию или только один раз?

ответ

1

Как указывал @Dai, второе и третье высказывания должны оцениваться в конце каждой итерации.

Данное поведение подробно описано в §8.8.3 спецификации языка C#. Перефразировать, это говорит о

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

заявление:

А при заявлении выполняется следующим образом:

  • Если для-инициализаторе присутствует, переменная инициализаторы или заявление выражения выполняются в том порядке, в котором они написаны. Этот шаг выполняется только один раз.
  • Если присутствует условие, оно оценивается.
  • Если для условия нет или если оценка дает значение true, управление передается встроенной инструкции. Когда и если элемент управления достигает конечной точки встроенного оператора, выражения for-iterator оцениваются последовательно, а затем выполняется другая итерация, начиная с оценки условия for на шаге выше.
  • Если условие условия присутствует и оценка дает ложь, управление передается в конечную точку оператора 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

Правильно, 2-й и 3-й компоненты оператора for оцениваются на каждой итерации.

Это:

for(x; y; z) a; 

эквивалентно:

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

Так y будет оцениваться более 1 раза, чем z.

+0

Спасибо. Я подумал, что, возможно, компилятор выполнит некоторую работу внутри параметров, но теперь мне пришло в голову, что это будет невозможно, потому что я, очевидно, мог бы изменить значение «обратного» булева внутри области цикла. –

Смежные вопросы