Какой правильный бесконечный цикл C # для (;;) или while (true)? [закрыто]

97

Еще в мои дни C / C ++, кодируя "бесконечный цикл" как

while (true)

казался мне более естественным и более очевидным, чем

for (;;)

Встреча с PC-lint в конце 1980-х и последующие обсуждения передового опыта избавили меня от этой привычки. С тех пор я закодировал циклы, используя forоператор управления. Сегодня, впервые за долгое время и, возможно, первой моей потребности в бесконечном цикле в качестве разработчика C #, я столкнулся с той же ситуацией. Один из них правильный, а другой нет?

Боб Кауфман
источник
5
Четыре идентичных ответа менее чем за две минуты. Неплохо.
Jon B,
5
Вы можете избежать целого религиозного спора, развернув бесконечный цикл. Это не займет много времени ...
Стивен Дарлингтон,
7
Просто из любопытства: почему для (;;) лучше в C / C ++?
Vilx
6
@Vilx, насколько я помню, старые компиляторы писали более эффективный код с for (;;), чем с while (1). Я уверен, что любой приличный современный компилятор выдаст практически идентичный код.
Стивен Дарлингтон,
4
Основываясь на комментариях Стивена и Серхио: 1. while(true)Требуется условие. for(;;)поэтому это лучшее представление для бесконечных циклов, которые безоговорочно повторяются. 2. Старые неоптимизирующие компиляторы, возможно, действительно оценивали цикл (true). 3. C - это минималистский язык со времен телетайпов, терминалов на 300 бод и 1-символьных имен переменных. В среде, где учитывается каждое нажатие клавиши, for(;;)это немного короче, чем while(true).
Ричард Дингуолл,

Ответы:

124
while(true)
{

}

Всегда то, что я использовал, и то, что я видел, как другие используют для цикла, который нужно разорвать вручную.

Адам Робинсон
источник
@RSolberg - это была жеребьевка между двумя похожими ответами, предложенными с интервалом в несколько секунд. Последующий комментарий Адама побудил меня принять ответ, основанный на использовании, а не на соглашении.
Боб Кауфман,
1
while и for могут быть сломаны вручную
Аллен Райс
2
К сожалению, этот ответ не отвечает на вопрос. Правильный ответ - «оба правильны».
Дэвид Р. Триббл,
2
@Loadmaster: Это зависит от вашего определения «правильности» (или, точнее, от того, какого рода «правильность» вы ищете).
Адам Робинсон
317

Компилятор C # преобразует оба

for(;;)
{
    // ...
}

и

while (true)
{
    // ...
}

в

{
    :label
    // ...
    goto label;
}

CIL для обоих одинаковый. Большинству людей while(true)легче читать и понимать. for(;;)довольно загадочный.

Источник:

Я еще немного испортил .NET Reflector и скомпилировал оба цикла с помощью «Оптимизировать код» в Visual Studio.

Оба цикла компилируются (с .NET Reflector):

Label_0000:
    goto Label_0000;

Скоро должны атаковать хищники.

Пьер-Ален Вижан
источник
7
да, просто дважды проверил, все тот же код IL, это должен быть принятый ответ, ИМО :)
Аллен Райс,
63
+1 для ссылки на xkcd
Икке
4
Чтобы быть педантичным, компилятор не преобразует одну форму оператора в другую; скорее, он генерирует идентичный код для обоих операторов. Этот код идентичен gotoоператору, кстати, что неудивительно.
Дэвид Р. Триббл,
1
а затем goto преобразуется в инструкцию jmp ..
Марко М.
25
так что очевидно, goto LOOPчто это правильный бесконечный цикл C # :)
Дастин Гетц,
61

Я думаю, что это может быть проще для чтения, и это определенно стандарт для использования в C #:

while(true)
{
   //Do My Loop Stuff
}
RSolberg
источник
19
@voyager: 1 не заменяет true в C #.
Адам Робинсон,
17
Обратите внимание, что while (1) недействителен. C #: Константа 1 не может быть преобразована в bool
Винко Врсалович
4
while(1)недействителен в C #, поскольку 1не является bool.
Павел Минаев
47

Gasp, используйте:

while (!false)
{

}

ИЛИ, как указал jsight , вы можете быть уверены вдвойне:

while (!false && true)
{
}

Пока на меня не кричали, это все тот же CIL-код, я проверил :)

Аллен Райс
источник
Лучший ответ на свете.
Ларри
38

Перефразируя пару старых шуток:

  1. Не используйте " for (;;) {}" - это заставит заявление плакать.
  2. Если, конечно, вы "не #define EVER ;;".
Бен Бланк
источник
25
Или #define ever (;;)что мне кажется более читабельным. for ever {}
Крис Лутц,
1
Я не думал, что можно сделать #define ever (;;) на C #, хотя шутка забавная :)
Аллен Райс,
1
Ах. Я программирую C на OS X. Я не знал, что препроцессор C # настолько кастрирован. Я даже не уверен, как я начал читать этот вопрос, у меня C # в качестве игнорируемого тега ...
Крис Лутц,
Препроцессор C # на самом деле не является препроцессором, по крайней мере, с точки зрения того, что предоставляют C, C ++, PL / 1 и даже макроассемблеры. Он только позволяет вам включать или отключать блоки кода, определяя / отменяя символы препроцессора.
Дэвид Р. Триббл,
6
Или даже лучше #define forever while(true)
:;
26

Если вы хотите перейти на старую школу, goto по-прежнему поддерживается в C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Для действительно бесконечного цикла это команда перехода. знак равно

JohnFx
источник
9
xkcd.com/292
Каллум Роджерс,
6
Я проголосовал за это с отрицательной оценки до нуля, но только из-за его юмора. Эй, все циклы в любом случае компилируются в коды операций JMP ассемблера, верно?
Дэвид Р. Триббл,
@Loadmaster: Спасибо, я просто предлагал это как еще один вариант, не обязательно одобряя его.
JohnFx
2
@serhio: Тем более избегает языковых конструкций из-под контроля, потому что вы что-то где-то читаете. Никакой языковой элемент сам по себе не является плохим, его можно использовать только плохо.
JohnFx 04
2
@serhio: Я видел мерзости против природы, использующие почти все возможные ключевые слова. Это не элемент языка, это программист. В любом случае, как отмечалось в моем предыдущем комментарии, я его не одобрял. Я просто включил это для полноты и легкого юмора.
JohnFx 05
21

Думаю, while (true)читабельнее.

Марплсофт
источник
10

В тех ситуациях, когда мне нужен был настоящий бесконечный цикл, я всегда использовал

while(true) {...}

Кажется, это лучше выражает намерение, чем пустой оператор for.

Майкл Петротта
источник
10

Лично я всегда отдавал предпочтение for(;;)именно потому, что у него нет условия (в отличие от того, while (true)которое имеет всегда верное условие ). Однако на самом деле это очень незначительный элемент стиля, о котором я не думаю, что стоит спорить в любом случае. Я еще не видел руководства по стилю C #, которое предписывало или запрещало любой подход.

Павел Минаев
источник
не стоит в .NET, когда компилятор преобразует ваш (плохо читаемый) для без условия в то время как с условием.
serhio 04
3
@serhio: объясните, пожалуйста, что вы имеете в виду под "преобразованием компилятора ... в while". С точки зрения программиста, компилятор преобразует высокоуровневый код в IL. В IL нет while(или for) циклов, только метки и переходы.
Павел Минаев
1
см. ответ Пьера-Алена Вижана.
serhio 05
3
Его ответ можно лучше перефразировать как просто «компилятор генерирует идентичный IL для обоих» (вы действительно не знаете, преобразует ли он что-либо на уровне AST и когда, и это детали реализации в любом случае). В любом случае это не объясняет, почему это «не стоит того в .NET». То же самое и с C ++, Java ...
Павел Минаев
6

Лично я предпочитаю for (;;)идиому (с точки зрения C / C ++). Хотя я согласен с тем, что while (true)это в некотором смысле более читабельно (и это то, что я использовал еще когда-то, даже в C / C ++), я обратился к использованию forидиомы, потому что

  • это выделяется

Я думаю, что тот факт, что цикл не завершается (обычным образом), заслуживает внимания, и я думаю, что он for (;;)делает это немного больше.

Майкл Берр
источник
наконец, используя это, мы подождем еще немного, чтобы программы скомпилировались (преобразование компиляции из for => while)
serhio
3
@serhio: Не совсем. Это не превращает его из forв while. Для обоих for (;;){}и while (true){}он генерирует новый while(true){}код. Смотрите этот ответ .
wchargin
6

Оригинальная книга K&R для C, из которой C # может проследить его происхождение, рекомендовала

for (;;) ...

для бесконечных циклов. Он недвусмысленен, легко читается и имеет долгую и благородную историю.

Приложение (февраль 2017 г.)

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

// Infinite loop
for (;;)
    ...

Или:

for (;;)    // Loop forever
    ...
Дэвид Р. Триббл
источник
1
да, но это для C, а не для C #.
serhio 05
1
Работает на C #. А язык C # произошел (косвенно) от C.
Дэвид Р. Триббл
4
Спустя 8 лет вы решили обновить свой ответ. Nice
Metoniem
4

Это должно быть while(true)не while(1)так while(1)неверен в C #, да;)

JRL
источник
3

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

Хотя мне нравится вот этот:

for (float f = 16777216f; f < 16777217f; f++) { } 
Крис Чилверс
источник
2
-1: не все поймут ваш «бесконечный цикл», читая код, возможно, кто-то может подумать, что это ошибка, и попытаться «исправить» ее ...
serhio 05
В C # f < 16777217fвсегда false... так что это никогда не зацикливается.
NetMage
2

Я предпочитаю чуть более «грамотный» код. На практике у меня гораздо больше шансов сделать что-то подобное:

bool shouldContinue = true;
while (shouldContinue)
{
    // ...

    shouldContinue = CheckSomething();
}
bobbymcr
источник
1
Тьфу. На самом деле это do ... while()замаскированная петля. Мне потребовалось всего несколько секунд, чтобы увидеть это. Если бы вы написали do ... while()цикл, это было бы понятно сразу. -1
sbi
зачем тратить время и ресурсы на объявление переменной, если можно использовать while (true)? На мой взгляд, это не имеет смысла
Вакасахмед
Я считаю его более читаемым, особенно если вы можете прикрепить конкретный значащий флаг, например, «while (! This.canceled)», чтобы указать, что отмена - единственный способ остановить цикл, «while (! ProcessExited)» - чтобы указать цикл должен работать до тех пор, пока не завершится внешний процесс и т. д. Есть много вещей, которые, возможно, «тратят впустую ресурсы», и которые являются абсолютно правильными во имя простоты сопровождения или удобочитаемости. «while (true)» не так уж и плохо, но, по моему опыту, обычно есть способ получше.
bobbymcr
1
+1. В большинстве случаев истинный бесконечный цикл - это не то, что на самом деле происходит, и у вас есть какое-то условие, в котором вы хотите остановиться (например, когда принтер горит).
Ли Райан,
1
… В этом случае вам следует использовать break.
Ry-
2

Даже я также говорю, что ниже лучше :)

while(true)
{

}
аниш
источник
1

Если вы играете в код-гольф, я бы посоветовал for(;;). Помимо этого, while(true)имеет то же значение и кажется более интуитивным. В любом случае, большинство программистов, вероятно, поймут оба варианта, так что это не имеет особого значения. Используйте то, что вам удобнее.

собеллианский
источник
2
если вы играете в гольф, то C # - неправильный язык.
SingleNegationElimination
1

С точки зрения читабельности кода while(true)на любом языке, который я считаю более понятным. С точки зрения того, как это видит компьютер, в сегодняшнем обществе очень эффективных компиляторов и интерпретаторов не должно быть никакой разницы.

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

Крис
источник
1

Единственная причина, которую я бы сказал for(;;), связана с ограничениями CodeDom (в то время как циклы не могут быть объявлены с помощью CodeDom, а циклы for рассматриваются как более общая форма как цикл итераций).

Это довольно слабая причина для выбора этого, кроме того факта, что forреализация цикла может использоваться как для обычного кода, так и для кода, созданного CodeDom. То есть может быть более стандартным.

Обратите внимание, что вы можете использовать фрагменты кода для создания whileцикла, но весь цикл должен быть фрагментом ...

Марк Синовец
источник
1

Оба они выполняют одну и ту же функцию, но обычно люди предпочитают while(true). Легко читать и понимать ...

абхинав
источник
0

Любое выражение, которое всегда возвращает истину, должно подходить для цикла while.

Пример:

1==1 //Just an example for the text stated before 
true
Джордж
источник
Зачем вам когда-либо заставлять его выполнять сравнение типа 1 = 1, когда true работает так же хорошо? Использование вычисленного выражения выглядит так же глупо, как определение константы вроде NUMBER_OF_ARMS = 598-3596;
JohnFx
Это пример ответа, указанного перед кодом :)
Джордж,