Какой правильный бесконечный цикл 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
}

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;

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



6
Я проголосовал за это с отрицательной оценки до нуля, но только из-за его юмора. Эй, все циклы в любом случае компилируются в коды операций JMP ассемблера, верно?
Дэвид Р. Триббл,

@Loadmaster: Спасибо, я просто предлагал это как еще один вариант, не обязательно одобряя его.
JohnFx

2
@serhio: Тем более избегает языковых конструкций из-под контроля, потому что вы что-то где-то читаете. Никакой языковой элемент сам по себе не является плохим, его можно использовать только плохо.
JohnFx 04

2
@serhio: Я видел мерзости против природы, использующие почти все возможные ключевые слова. Это не элемент языка, это программист. В любом случае, как отмечалось в моем предыдущем комментарии, я его не одобрял. Я просто включил это для полноты и легкого юмора.
JohnFx 05


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 #, да;)


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();
}

1
Тьфу. На самом деле это do ... while()замаскированная петля. Мне потребовалось всего несколько секунд, чтобы увидеть это. Если бы вы написали do ... while()цикл, это было бы понятно сразу. -1
sbi

зачем тратить время и ресурсы на объявление переменной, если можно использовать while (true)? На мой взгляд, это не имеет смысла
Вакасахмед

Я считаю его более читаемым, особенно если вы можете прикрепить конкретный значащий флаг, например, «while (! This.canceled)», чтобы указать, что отмена - единственный способ остановить цикл, «while (! ProcessExited)» - чтобы указать цикл должен работать до тех пор, пока не завершится внешний процесс и т. д. Есть много вещей, которые, возможно, «тратят впустую ресурсы», и которые являются абсолютно правильными во имя простоты сопровождения или удобочитаемости. «while (true)» не так уж и плохо, но, по моему опыту, обычно есть способ получше.
bobbymcr

1
+1. В большинстве случаев истинный бесконечный цикл - это не то, что на самом деле происходит, и у вас есть какое-то условие, в котором вы хотите остановиться (например, когда принтер горит).
Ли Райан,

1
… В этом случае вам следует использовать break.
Ry-


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

Это пример ответа, указанного перед кодом :)
Джордж,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.