Когда вам нужно перебрать читателя, где количество элементов для чтения неизвестно, и единственный способ сделать это - продолжить чтение до конца.
Это часто место, где вам нужен бесконечный цикл.
Существует Всегда
true
что указывает на то , должно быть ,break
илиreturn
заявление где - то внутри блока.int offset = 0; while(true) { Record r = Read(offset); if(r == null) { break; } // do work offset++; }
Существует метод двойного чтения для цикла.
Record r = Read(0); for(int offset = 0; r != null; offset++) { r = Read(offset); if(r != null) { // do work } }
Существует один цикл чтения пока. Не все языки поддерживают этот метод .
int offset = 0; Record r = null; while((r = Read(++offset)) != null) { // do work }
Мне интересно, какой подход наименее вероятен для введения ошибки, наиболее читаемый и широко используемый.
Каждый раз, когда мне приходится писать один из них, я думаю, что «должен быть лучший путь» .
c#
code-quality
readability
Reactgular
источник
источник
Ответы:
Я бы сделал шаг назад сюда. Вы концентрируетесь на придирчивых деталях кода, но упускаете общую картину. Давайте посмотрим на один из ваших примеров циклов:
В чем смысл этого кода? Смысл в том, чтобы «сделать некоторую работу с каждой записью в файле». Но это не то, на что похож код . Код выглядит как «поддерживать смещение. Откройте файл. Введите цикл без конечного условия. Прочитайте запись. Проверьте на ничтожность». Все это, прежде чем мы приступим к работе! Вопрос, который вы должны задать: « Как я могу сделать внешний вид этого кода соответствующим его семантике? » Этот код должен быть:
Теперь код читается как его намерение. Отделите свои механизмы от вашей семантики . В своем исходном коде вы смешиваете механизм - детали цикла - с семантикой - работу, проделанную с каждой записью.
Теперь мы должны реализовать
RecordsFromFile()
. Каков наилучший способ реализации этого? Какая разница? Это не тот код, на который будет смотреть кто-либо. Это базовый код механизма и его длина в десять строк. Напиши как хочешь. Как насчет этого?Теперь, когда мы манипулируем лениво вычисляемой последовательностью записей, возможны все виды сценариев:
И так далее.
Каждый раз, когда вы пишете цикл, спрашивайте себя: «Этот цикл читается как механизм или как смысл кода?» Если ответ «как механизм», попробуйте переместить этот механизм в его собственный метод и напишите код, чтобы значение стало более видимым.
источник
Вам не нужен бесконечный цикл. Вы никогда не должны нуждаться в этом в сценариях чтения C #. Это мой предпочтительный подход, предполагающий, что вам действительно нужно поддерживать смещение:
Этот подход учитывает тот факт, что для читателя существует шаг настройки, поэтому существует два вызова метода чтения.
while
Состояние находится в верхней части петли, только в случае , если нет данных на все в читателе.источник
Ну, это зависит от вашей ситуации. Но одно из наиболее "C # -ish" решений, о которых я могу подумать, - это использовать встроенный интерфейс IEnumerable и цикл foreach. Интерфейс для IEnumerator вызывает MoveNext только с true или false, поэтому размер может быть неизвестен. Тогда ваша логика завершения записывается один раз - в счетчике - и вам не нужно повторять более чем в одном месте.
MSDN предоставляет пример IEnumerator <T> . Вам также потребуется создать IEnumerable <T>, чтобы вернуть IEnumerator <T>.
источник
Когда у меня есть операции инициализации, условия и приращения, мне нравится использовать циклы for таких языков, как C, C ++ и C #. Как это:
Или это, если вы думаете, что это более читабельно. Я лично предпочитаю первый.
источник