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


97

Повернувшись до моїх C / C ++ днів, кодуючи "нескінченну петлю" як

while (true)

відчував себе більш природним і здавався мені більш очевидним на відміну від

for (;;)

Зустріч із PC-обличчям наприкінці 1980-х та подальші обговорення найкращих практик порушили мене від цієї звички. З тих пір я кодував цикли за допомогою forоператора управління. Сьогодні, вперше за довгий час, і, можливо, моя перша потреба у нескінченному циклі як розробник C #, я стикаюся з тією ж ситуацією. Чи одна з них правильна, а інша ні?


5
Чотири однакові відповіді за менше двох хвилин. Непогано.
Джон Б

5
Ви могли уникнути цілого релігійного аргументу, розкрутивши свій нескінченний цикл. Не повинно зайняти багато часу
Стівен Дарлінгтон

7
Просто з цікавості: чому для (;;) краще в C / C ++?
Vilx-

6
@Vilx, наскільки я пам'ятаю, старі компілятори використовували для написання більш ефективного коду за допомогою (;;), ніж while (1). Я впевнений, що будь-який пристойний сучасний компілятор видасть майже однаковий код.
Стівен Дарлінгтон,

4
Спираючись на коментарі Стівена та Серхіо: 1. while(true)потрібна умова. for(;;)тому є кращим поданням для нескінченних циклів, які повторюються беззастережно. 2. Старі неоптимізовані компілятори, можливо, насправді оцінили те, (true)як вони цикла. 3. С - мінімалістична мова з часів телетипів, 300 бод-терміналів та 1-знакова назва змінних. В умовах, коли кожен ключовий штрих рахується, for(;;)це зовсім трохи коротше, ніж while(true).
Річард Дінгволл

Відповіді:


124
while(true)
{

}

Це завжди те, що я використовував, і те, що я бачив, інші використовують для циклу, який потрібно розірвати вручну.


@RSolberg - це було розкидання між двома подібними відповідями, запропонованими протягом секунд одна від одної. Наступний коментар Адама змусив мене прийняти відповідь на основі використання, а не умовності.
Боб Кауфман

1
в той час як і за те, і те, і інше можна зламати вручну
Аллен Райс

2
На жаль, ця відповідь не дає відповіді на запитання. Правильна відповідь - «обидва є правильними».
David R Tribble

2
@Loadmaster: Це залежить від вашого визначення поняття "правильний" (вірніше, якого типу "правильності" ви домагаєтесь).
Адам Робінсон

314

Компілятор 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
Ikke

4
Щоб бути педантичним, компілятор не перетворює одну форму заяви в іншу; швидше, він генерує однаковий код для обох висловлювань. Цей код ідентичний gotoтвердженню, btw, що не дивно.
David R Tribble

1
а потім гото перекладається на інструкцію jmp ..
Марко М.

25
так очевидно, що goto LOOPце правильний цикл C # безмежно :)
Дастін Гец

61

Я думаю, що це може бути простішим для читання і, безумовно, є стандартом для використання в C #:

while(true)
{
   //Do My Loop Stuff
}

19
@voyager: 1 не замінює 'true' у C #.
Адам Робінсон

17
Зауважте, що поки (1) недійсний C #: Постійний 1 не можна перетворити на bool
Вінко Врсалович

4
while(1)не вірно в C #, оскільки 1це не a bool.
Павло Мінаєв

47

Задихайтесь, використовуйте:

while (!false)
{

}

АБО як вказувало сузір'я , ви можете бути впевнені в цьому:

while (!false && true)
{
}

Перш ніж люди кричать на мене, це все той же код CIL, я перевірив :)


Найкраща відповідь коли-небудь.
Ларрі

38

Щоб повторити пару старих анекдотів:

  1. Не використовуйте " for (;;) {}" - це змушує заяву плакати.
  2. Якщо, звичайно, ви " #define EVER ;;".

25
Або, #define ever (;;)що я вважаю більш читабельним. for ever {}
Кріс Лутц

1
Я не думав, що ти можеш зробити #define коли-небудь (;;) у C #, проте, жарт смішна :)
Аллен Райс

1
Ага. Я програмую C на OS X. Я не знав, що препроцесор C # був так кастрований. Я навіть не впевнений, як я почав читати це питання, у мене є C # як ігнорований тег ...
Кріс Лутц

Препроцесор C # насправді не є препроцесором, принаймні не з точки зору того, що надають C, C ++, PL / 1 і навіть макроскладачі. Це дозволяє лише вмикати або вимикати блоки коду шляхом визначення / невизначення символів препроцесора.
David R Tribble

6
Або ще краще #define forever while(true)
:;

26

Якщо ви хочете пройти стару школу, goto все ще підтримується на C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Для справді нескінченного циклу це команда go-to. =)



6
Я відмовив це від негативної оцінки до нуля, але тільки через її гумористичну цінність. Гей, усі петлі все-таки збираються в опкоди асемблера JMP, правда?
David R Tribble

@Loadmaster: Дякую, я просто викинув його там як інший варіант, не обов'язково схвалюючи його.
JohnFx

2
@serhio: Тим більше уникати мовних конструкцій поза рукою, бо десь щось читаєш. Жоден мовний елемент сам по собі не поганий, його можна використовувати лише поганими способами.
JohnFx

2
@serhio: Я бачив гидоти проти природи, використовуючи майже всі можливі ключові слова. Це не мовний елемент, а програміст. У будь-якому випадку, як було зазначено в моєму попередньому коментарі, я його не схвалював. Я просто включав це для повноти та гумору.
JohnFx


10

У тих ситуаціях, коли мені потрібна була справжня нескінченна петля, я завжди користувався

while(true) {...}

Здається, він виражає намір краще, ніж порожній для висловлювання.


10

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


не варто в .NET, коли компілятор через деякий час перетворює ваш (погано читається) на без умови з умовою.
serhio

3
@serhio: поясніть, будь ласка, що ви маєте на увазі під "перетворенням компілятора ... у while". Що стосується програміста, компілятор перетворює код високого рівня в IL. У IL немає циклів while(або for), лише мітки та готи.
Павло Мінаєв

1
дивіться відповідь П'єра-Алена Віжаанта.
serhio

3
Його відповідь можна переформулювати, як просто "компілятор генерує однаковий ІЛ для обох" (ви насправді не знаєте, чи і коли це щось трансформує на рівні AST, і це деталь реалізації у будь-якому випадку). У будь-якому випадку, це не пояснює, чому "не варто в .NET". Те саме стосується і C ++, Java ...
Павло Мінаєв

6

Я особисто віддаю перевагу for (;;)ідіомі (виходячи з точки зору C / C ++). Хоча я згоден, що while (true)сенс є більш читабельним у певному сенсі (і це те, що я використовував назад, коли навіть в C / C ++), я звернувся до використання forідіоми, оскільки:

  • це виділяється

Я думаю, що той факт, що цикл не припиняється (звичайним чином), варто «викликнути», і я думаю, що це for (;;)робить трохи більше.


нарешті, використовуючи це, ми зачекаємо ще трохи, що програми компілюють (компілювати перетворення з для => в той час)
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 #.
серхіо

1
Він працює в C #. А мова C # була похідною (опосередковано) від C.
David R Tribble

4
Через 8 років ви вирішили оновити свою відповідь. Ніцца
Metoniem

4

Це повинно бути while(true)НЕ while(1)так while(1)невірний в C #, так;)


2

Як варіант, можна сказати, що наявність нескінченного циклу в будь-якому випадку є поганою практикою, оскільки йому потрібна умова виходу, якщо програма дійсно не працює назавжди. Однак, якщо це стосується крилатої ракети, я прийму чіткого умови виходу, можливо, не потрібно.

Хоча мені це подобається:

for (float f = 16777216f; f < 16777217f; f++) { } 

2
-1: не всі зрозуміють ваш "нескінченний цикл" читання коду, можливо, хтось міг подумати, що це помилка, і спробувати її "виправити" ...
Серхіо

У C # f < 16777217fзавжди false... так що це ніколи не циклічно.
NetMage

2

Я віддаю перевагу трохи більш "грамотному" коду. Я набагато більше шансів зробити щось подібне на практиці:

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

    shouldContinue = CheckSomething();
}

1
Тьфу. Фактично, це do ... while()петля в маскуванні. На це мені знадобилося лише кілька секунд. Якби ви написали do ... while()цикл, це було б зрозуміло відразу. -1
sbi

навіщо витрачати час та ресурси, оголошуючи змінну, коли ви можете використовувати while (true)? На мою думку це не має сенсу
waqasahmed

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

1
+1. У більшості випадків справжній нескінченний цикл - це не те, що відбувається насправді, і у вас є певна умова, де ви хочете зупинитись (наприклад, коли принтер загорівся).
Лі Лі Раян

1
... у цьому випадку вам слід використовувати break.
Ри-


1

Якщо ви займаєтеся кодовим гольфом, я б запропонував for(;;). Крім того, while(true)має те саме значення і здається більш інтуїтивним. У кожному разі, більшість кодерів, швидше за все, зрозуміють обидва варіанти, тому це насправді не має значення. Використовуйте найзручніше.


2
якщо ви граєте в гольф, тоді C # - це все-таки неправильна мова.
SingleNegationElimination

1

Єдина причина, яку я сказав би for(;;) є обмеження CodeDom (тоді як цикли не можуть бути оголошені за допомогою CodeDom, а для циклів розглядаються як більш загальна форма як ітераційний цикл).

Це досить нещільна причина вибрати інший, ніж той факт, що for циклу може використовуватися як для звичайного коду, так і для коду, згенерованого CodeDom. Тобто вона може бути і більш стандартною.

Як примітка, ви можете використовувати фрагменти коду для створення whileциклу, але весь цикл повинен бути фрагментом ...


1

Вони обоє мають однакову функцію, але люди, як правило, віддають перевагу while(true). Це легко читати і розуміти ...


0

Будь-який вираз, який завжди повертає true, повинен бути добре для циклу while.

Приклад:

1==1 //Just an example for the text stated before 
true

Чому б вам коли-небудь змусити його робити порівняння, як 1 = 1, коли істина працює так само добре? Використання обчислюваного виразу здається настільки ж безглуздим, як визначення такої константи, як NUMBER_OF_ARMS = 598-3596;
JohnFx

Це приклад відповіді, зазначеної перед кодом :)
Джордж

0

З точки зору читабельності коду while(true) будь-якою мовою, я вважаю, має більше сенсу. З точки зору того, як це бачить комп'ютер, насправді не повинно бути різниць у сучасному суспільстві дуже ефективних укладачів та перекладачів.

Якщо є різниця в продуктивності, я впевнений, що переклад на MSIL буде оптимізований. Ви можете перевірити це, якщо цього дуже хотіли.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.