Использование синтаксиса foreach (...) при увеличении переменной индекса внутри цикла - PullRequest
3 голосов
/ 12 ноября 2008

Когда я смотрю на код C #, я часто вижу такие шаблоны:

DataType[] items = GetSomeItems();
OtherDataType[] itemProps = new OtherDataType[items.Length];

int i = 0;
foreach (DataType item in items)
{
    // Do some stuff with item, then finally
    itemProps[i] = item.Prop;
    i++;
}

Цикл for выполняет итерации по объектам в items, но также сохраняет счетчик (i) для итерации по itemProps. Лично мне не нравится этот дополнительный i слоняющийся вокруг, и вместо этого вероятно сделал бы что-то вроде:

DataType[] items = GetSomeItems();
OtherDataType[] itemProps = new OtherDataType[items.Length];

for (int i = 0; i < items.Length; i++)
{
    // Do some stuff with items[i], then finally
    itemProps[i] = items[i].Prop;
}

Возможно, есть какая-то польза от первого подхода, о котором я не знаю? Это результат того, что все пытаются использовать этот причудливый синтаксис foreach (...)? Мне интересно ваше мнение по этому поводу.

Ответы [ 7 ]

7 голосов
/ 12 ноября 2008

Если вы используете C # 3.0, это будет лучше;

OtherDataType[] itemProps = items.Select(i=>i.Prop).ToArray();
4 голосов
/ 12 ноября 2008

Если я вне массива, то if будет доступен после завершения цикла. Если вы хотите подсчитать количество элементов, а в коллекции нет свойства .Count или .UBound, это может быть полезно.

Как и вы, я бы обычно использовал второй метод, выглядит для меня намного чище.

2 голосов
/ 12 ноября 2008

В этом случае я так не думаю. Иногда, однако, коллекция не реализует this[int index], но она реализует GetEnumerator (). В последнем случае у вас нет большого выбора.

1 голос
/ 12 ноября 2008

Давайте не будем забывать, что в некоторых коллекциях не реализован оператор прямого доступа [] и что вам нужно выполнять итерации с помощью интерфейса IEnumerable, к которому проще всего обращаться с помощью foreach ().

1 голос
/ 12 ноября 2008

foreach (элемент DataType в элементах) Этот цикл foreach проясняет, что вы перебираете все элементы DataType, ну да, элементы. Может быть, это делает код немного длиннее, но это не «плохой» код. Для другого цикла for вам нужно проверить внутри скобок, чтобы иметь представление о том, что этот цикл используется.

Проблема этого примера заключается в том, что вы перебираете два разных массива в одно и то же время, что мы делаем не часто ... поэтому мы застряли между двумя стратегиями ... либо мы немного взломали «Причудливый, как вы это называете, или мы вернемся к старому, а не так любимому (int i = 0; i ...). (Есть и другие способы, кроме этих 2, конечно)

Итак, я думаю, что в Vim vs Emacs возвращаются ваши вопросы в цикле For vs Foreach :) Люди, которым нравится for (), скажут, что этот foreach бесполезен, может привести к проблемам с производительностью и просто огромен. Люди, которые предпочитают foreach, скажут что-то вроде: нам не важно, есть ли две дополнительные строки, если мы сможем прочитать код и легко его обслуживать.

Наконец, первый пример i находится вне области видимости, второй - внутри ... причины тому ?! Потому что, если вы используете I вне вашего foreach, я бы назвал по-другому. И, на мой взгляд, я предпочитаю пути foreach, потому что вы сразу видите, что происходит. Вам также не нужно думать о том, является ли это <или =. Вы сразу же знаете, что перебираете весь список, однако, к сожалению, люди забудут о i ++ в конце: D Итак, я говорю Vim! </p>

1 голос
/ 12 ноября 2008

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

Я не помню всех аргументов в голове, но они хорошо описаны в Effective C # , который рекомендуется прочитать.

1 голос
/ 12 ноября 2008

Некоторые структуры данных не очень подходят для произвольного доступа, но их можно очень быстро повторять (деревья, связанные списки и т. Д.). Так что, если вам нужно перебрать одну из них, но по какой-то причине вам нужен подсчет, вы обречены пойти ужасным путем ...

...