Что касается соглашений об именах переменных, следует ли называть итераторы i или что-то более семантическое, например count? Если вы не используете i, почему бы и нет? Если вы считаете, что i приемлемо, есть ли случаи итерации, когда его не следует использовать?
Является ли переменная с именем i неприемлемой?
Ответы (21)
Полагаю, это зависит от контекста. Если вы просматриваете набор объектов в некоторой коллекции, то из контекста должно быть довольно очевидно, что вы делаете.
for(int i = 0; i < 10; i++)
{
// i is well known here to be the index
objectCollection[i].SomeProperty = someValue;
}
Однако, если из контекста не сразу понятно, что вы делаете, или если вы вносите изменения в индекс, вам следует использовать имя переменной, которое более показательно для использования.
for(int currentRow = 0; currentRow < numRows; currentRow++)
{
for(int currentCol = 0; currentCol < numCols; currentCol++)
{
someTable[currentRow][currentCol] = someValue;
}
}
«i» означает «счетчик циклов» для программиста. В этом нет ничего плохого.
Вот еще один пример того, что совершенно нормально:
foreach (Product p in ProductList)
{
// Do something with p
}
Я обычно использую i, j, k для очень локализованных циклов (существуют только в течение короткого периода с точки зрения количества исходных строк). Для переменных, которые существуют в большей исходной области, я обычно использую более подробные имена, чтобы я мог видеть, для чего они нужны, без поиска в коде.
Кстати, я думаю, что соглашение об именах для них пришло из раннего языка Fortran, где я был первой целочисленной переменной (A - H были числами с плавающей запятой)?
i вполне допустимо. Однако за семестр я многому научился у своего учителя C ++, который отказался от кода, у которого не было описательного имени для каждой отдельной переменной. Простой акт называния всего описательного заставил меня больше думать о своем коде, и после этого курса я писал лучшие программы, не благодаря изучению C ++, а благодаря тому, что научился все называть. В Code Complete есть несколько хороших слов на ту же тему.
i в порядке, но что-то вроде этого - нет:
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
string s = datarow[i][j].ToString(); // or worse
}
}
Очень часто программисты случайно меняют местами i и j в коде, особенно если у них плохое зрение или их тема Windows - «хот-дог». Для меня это всегда «запах кода» - это редкость, когда с ним не облажались.
i настолько распространен, что приемлем даже для людей, которые любят описательные имена переменных.
Абсолютно неприемлемо (и грех в моей книге) использование i, j или k в любом другом контексте, кроме как целочисленный индекс в цикле .... например.
foreach(Input i in inputs)
{
Process(i);
}
я определенно приемлемый. Не уверен, какое оправдание мне нужно, но я использую его постоянно, как и другие очень уважаемые программисты.
Думаю, социальная проверка :)
Да, на самом деле это предпочтительнее, поскольку любой программист, читающий ваш код, поймет, что это просто итератор.
В чем смысл использования i вместо более конкретного имени переменной? Чтобы сэкономить 1 секунду или 10 секунд, а может быть, даже 30 секунд размышлений и набора текста?
Какова стоимость использования i? Может ничего. Может быть, код настолько прост, что использовать i можно. Но, может быть, может быть, использование i заставит разработчиков, которые придут к этому коду в будущем, задуматься на мгновение "что я здесь имею в виду?" Им придется подумать: «Это индекс, счетчик, смещение, флаг?» Им придется подумать: «Безопасно ли это изменение, правильно ли я выйду на 1?»
Использование i экономит время и интеллектуальные усилия при написании кода, но может в конечном итоге потребовать дополнительных интеллектуальных усилий в будущем или, возможно, даже привести к непреднамеренному появлению дефектов из-за неправильного понимания кода.
Вообще говоря, большая часть разработки программного обеспечения - это поддержка и расширение, поэтому время, потраченное на чтение вашего кода, значительно превышает время, потраченное на его написание.
Очень легко развить привычку использовать значащие имена повсюду, и как только у вас появится эта привычка, вам понадобится всего несколько секунд, чтобы написать код со значимыми именами, но тогда у вас есть код, который легче читать, легче понимать и многое другое. очевидно правильно.
Я использую i для коротких петель.
Причина, по которой все в порядке, заключается в том, что я считаю совершенно неправдоподобным, чтобы кто-то мог увидеть объявление типа итератора с инициализатором, а затем три строки спустя утверждают, что неясно, что представляет собой переменная. Они просто притворяются, потому что решили, что «значимые имена переменных» должны означать «длинные имена переменных».
Причина, по которой я на самом деле это делаю, заключается в том, что я нахожу, что использование чего-то, не связанного с конкретной задачей, и что я буду использовать только в небольшом объеме, избавляет меня от беспокойства о том, что я могу использовать имя, которое вводит в заблуждение, или двусмысленно, или когда-нибудь будет полезно для чего-то еще в более широком масштабе. Причина, по которой это «i», а не «q» или «count», просто условность, заимствованная из математики.
Я не использую i, если:
- Тело петли не маленькое, или
- итератор делает что-либо, кроме продвижения (или отступления) от начала диапазона до конца цикла:
i не обязательно должен идти с приращением 1, если приращение является последовательным и четким, и, конечно, может остановиться до конца итерации, но если он когда-либо изменит направление или не будет изменен итерацией цикла (включая дьявольское использование iterator.insertAfter () в прямом цикле), я стараюсь не забывать использовать что-то другое. Это сигнализирует, что «это не просто тривиальная переменная цикла, следовательно, это может быть нетривиальный цикл».
Если «что-то более семантическое» - «итератор», то нет причин не использовать i; это хорошо понятная идиома.
Я думаю, что я вполне приемлем в ситуациях цикла. Я всегда считал это довольно стандартным и никогда не сталкивался с проблемами интерпретации, когда я использовался в этом случае. Циклы foreach становятся немного сложнее, и я думаю, что это действительно зависит от вашей ситуации. Я редко, если когда-либо, использую i в foreach, только в циклах for, поскольку считаю, что i в этих случаях слишком неинформативен. для foreach я пытаюсь использовать аббревиатуру циклического типа объекта. например:
foreach(DataRow dr in datatable.Rows)
{
//do stuff to/with datarow dr here
}
в любом случае, только мои 0,02 доллара.
Будет полезно, если вы назовете его чем-то, что описывает то, через что он проходит. Но обычно я просто использую i.
Пока вы используете i для подсчета циклов или часть индекса, который идет от 0 (или 1 в зависимости от PL) до n, я бы сказал, что со мной все в порядке.
В противном случае его, вероятно, легко назвать чем-то значимым, это больше, чем просто индекс.
Я должен отметить, что i и j также являются математическими обозначениями для матричных индексов. И обычно вы перебираете массив. Так что в этом есть смысл.
Если вы временно используете его внутри простого цикла и очевидно, что вы делаете. Тем не менее, нет ли другого короткого слова, которое вы могли бы использовать вместо этого?
i широко известен как итератор цикла, поэтому вы с большей вероятностью запутаете программистов, обслуживающих техобслуживание, если будете использовать его вне цикла, но если вы используете что-то более наглядное (например, filecounter), это сделает код более приятным.
По-разному. Если вы перебираете какой-то конкретный набор данных, я думаю, что имеет смысл использовать описательное имя. (например, filecounter, как предложил Дэн).
Однако, если вы выполняете произвольный цикл, i приемлемо. Как описал мне один товарищ по работе, i - это соглашение, которое означает, что "эта переменная изменяется только конструкцией цикла for. Если это не так, не используйте i"
Использование i, j, k для счетчиков цикла INTEGER восходит к ранним дням FORTRAN.
Лично у меня нет проблем с ними, пока они являются счетчиками INTEGER.
Но потом я вырос на ФОРТРАНЕ!
Мне кажется, что концепция использования одной буквы подходит для "простых" циклов, однако я давно научился использовать двойные буквы, и это отлично сработало.
на прошлой неделе я задал аналогичный вопрос, и следующее является частью мой собственный ответ:
// recommended style ● // "typical" single-letter style
●
for (ii=0; ii<10; ++ii) { ● for (i=0; i<10; ++i) {
for (jj=0; jj<10; ++jj) { ● for (j=0; j<10; ++j) {
mm[ii][jj] = ii * jj; ● m[i][j] = i * j;
} ● }
} ● } на тот случай, если выгода не сразу очевидна: поиск по коду любой отдельной буквы обнаружит много вещей, которые не то, что вы находясь в поиске. буква i довольно часто встречается в коде, где это не та переменная, которую вы ищете.
Я делаю это уже как минимум 10 лет.
обратите внимание, что многие люди прокомментировали, что оба из вышеперечисленных "уродливы" ...
Я собираюсь пойти против течения и сказать нет.
Для толпы, которая говорит, что «i понимается как итератор», это может быть правдой, но для меня это эквивалент комментариев типа «Присвойте значение 5 переменной Y». Имена переменных, такие как комментарий, должны объяснять, почему / что не как.
Чтобы использовать пример из предыдущего ответа:
for(int i = 0; i < 10; i++)
{
// i is well known here to be the index
objectCollection[i].SomeProperty = someValue;
}
Неужели намного сложнее просто использовать такое значимое имя?
for(int objectCollectionIndex = 0; objectCollectionIndex < 10; objectCollectionIndex ++)
{
objectCollection[objectCollectionIndex].SomeProperty = someValue;
}
Допустим, имя (заимствованное) имя переменной objectCollection тоже имеет довольно плохое имя.