Quelle est la boucle infinie C # correcte, pour (;;) ou while (true)? [fermé]


97

De retour dans mes jours C / C ++, coder une "boucle infinie" comme

while (true)

me semblait plus naturel et me semblait plus évident que

for (;;)

Une rencontre avec PC-lint à la fin des années 80 et des discussions sur les meilleures pratiques qui ont suivi m'ont brisé cette habitude. Depuis, j'ai codé les boucles en utilisant l' forinstruction de contrôle. Aujourd'hui, pour la première fois depuis longtemps, et peut-être mon premier besoin d'une boucle infinie en tant que développeur C #, je suis confronté à la même situation. L'un d'eux est-il correct et l'autre non?


5
Quatre réponses identiques en moins de deux minutes. Pas mal.
Jon B le

5
Vous pourriez éviter tout l'argument religieux en déroulant votre boucle infinie. Ne devrait pas prendre longtemps ...
Stephen Darlington

7
Juste par curiosité: pourquoi for (;;) est-il meilleur en C / C ++?
Vilx-

6
@Vilx si je me souviens bien, les anciens compilateurs écrivaient du code plus efficace avec for (;;) qu'avec while (1). Je suis sûr que tout compilateur moderne décent produira un code à peu près identique.
Stephen Darlington

4
S'appuyant sur les commentaires de Stephen et Serhio: 1. while(true)nécessite une condition. for(;;)est donc une meilleure représentation pour les boucles infinies qui se répètent inconditionnellement. 2. Les anciens compilateurs sans optimisation ont peut-être en fait évalué le (true)lors de sa boucle. 3. C est un langage minimaliste de l'époque des télétypes, des terminaux à 300 bauds et des noms de variables à 1 caractère. Dans un environnement où chaque coup de touche compte, for(;;)c'est un peu plus court que while(true).
Richard Dingwall

Réponses:


124
while(true)
{

}

C'est toujours ce que j'ai utilisé et ce que j'ai vu d'autres utiliser pour une boucle qui doit être interrompue manuellement.


@RSolberg - c'était un tirage au sort entre les deux réponses similaires offertes en quelques secondes l'une de l'autre. Le commentaire complémentaire d'Adam m'a conduit à accepter une réponse basée sur l'usage plutôt que sur la convention.
Bob Kaufman le

1
tandis que et pour peuvent tous deux être cassés manuellement
Allen Rice

2
Malheureusement, cette réponse ne répond pas à la question. La bonne réponse est "les deux sont corrects".
David R Tribble

2
@Loadmaster: Cela dépend de votre définition de «correct» (ou plutôt du type de «correction» que vous recherchez).
Adam Robinson

317

Le compilateur C # transformera les deux

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

et

while (true)
{
    // ...
}

dans

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

Le CIL pour les deux est le même. La plupart des gens trouvent que while(true)c'est plus facile à lire et à comprendre. for(;;)est plutôt cryptique.

La source:

J'ai un peu plus dérangé avec .NET Reflector , et j'ai compilé les deux boucles avec le "Optimize Code" dans Visual Studio.

Les deux boucles se compilent dans (avec .NET Reflector):

Label_0000:
    goto Label_0000;

Les rapaces devraient attaquer bientôt.


7
ouais, juste vérifié, c'est le même code IL, cela devrait être la réponse acceptée IMO :)
Allen Rice

63
+1 pour la référence xkcd
Ikke

4
Pour être pédant, le compilateur ne transforme pas une forme de déclaration en une autre; il génère plutôt un code identique pour les deux instructions. Ce code est identique à une gotodéclaration, btw, ce qui n'est pas surprenant.
David R Tribble

1
puis le goto est traduit en une instruction jmp ..
Marco M.

25
est donc évidemment goto LOOPla bonne boucle infinie C # :)
Dustin Getz

61

Je pense que cela peut être plus facile à lire et c'est certainement la norme à utiliser en C #:

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

19
@voyager: 1 ne remplace pas «true» en C #.
Adam Robinson

17
Notez que while (1) est invalide C #: La constante 1 ne peut pas être convertie en
booléen

4
while(1)n'est pas valide en C #, car 1n'est pas un bool.
Pavel Minaev

47

Gasp, utilisez:

while (!false)
{

}

OU comme jsight l'a souligné, vous voudrez peut-être être doublement sûr:

while (!false && true)
{
}

Avant que les gens me crient dessus, c'est le même code CIL, j'ai vérifié :)


Meilleure réponse jamais.
Larry

38

Pour ressasser quelques vieilles blagues:

  1. N'utilisez pas " for (;;) {}" - cela fait pleurer la déclaration.
  2. Sauf, bien sûr, vous " #define EVER ;;".

25
Ou #define ever (;;)ce que je pense est plus lisible. for ever {}
Chris Lutz

1
Je ne pensais pas que vous pouviez faire une #define jamais (;;) en C #, cependant, la blague est drôle :)
Allen Rice

1
Ah. Je programme C sur OS X. Je ne savais pas que le préprocesseur C # était si castré. Je ne sais même pas comment j'ai commencé à lire cette question, j'ai C # comme tag ignoré ...
Chris Lutz

Le préprocesseur C # n'est pas vraiment un préprocesseur, du moins pas en termes de ce que les assembleurs C, C ++, PL / 1 et même de macro fournissent. Il vous permet uniquement d'activer ou de désactiver des blocs de code en définissant / annulant des symboles de préprocesseur.
David R Tribble

6
Ou encore mieux #define forever while(true)
:;

26

Si vous voulez aller à l'ancienne, goto est toujours pris en charge en C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Pour une boucle vraiment infinie, c'est la commande incontournable. =)



6
Je l'ai relevé d'une note négative à zéro, mais uniquement à cause de sa valeur d'humour. Hé, toutes les boucles sont de toute façon compilées dans les opcodes de l'assembleur JMP, non?
David R Tribble le

@Loadmaster: Merci, je l'ai juste lancé comme une autre option, sans nécessairement l'approuver.
JohnFx

2
@serhio: Éviter encore plus les constructions de langage parce que vous lisez quelque chose quelque part. Aucun élément de langage en lui-même n'est mauvais, il ne peut être utilisé que de mauvaises manières.
JohnFx

2
@serhio: J'ai vu des abominations contre la nature en utilisant à peu près tous les mots clés possibles. Ce n'est pas l'élément de langage, c'est le programmeur. En tout cas, comme indiqué dans mon commentaire précédent, je ne l'appuyais pas. Je l'ai juste inclus par souci d'exhaustivité et un picotement d'humour.
JohnFx


10

Dans les situations où j'avais besoin d'une véritable boucle infinie, j'ai toujours utilisé

while(true) {...}

Il semble mieux exprimer l'intention qu'une déclaration vide pour.


10

Personnellement, j'ai toujours préféré for(;;)précisément parce qu'il n'a pas de condition (par opposition à celle while (true)qui en a toujours une). Cependant, c'est vraiment un point de style très mineur, dont je ne pense pas qu'il vaut la peine de discuter de toute façon. Je n'ai pas encore vu de directive de style C # qui imposait ou interdisait l'une ou l'autre approche.


ne vaut pas dans .NET, lorsque le compilateur transforme votre (mauvaise lecture) pour sans condition en un moment avec condition.
serhio

3
@serhio: veuillez expliquer ce que vous entendez par "compilateur transforme ... en while". En ce qui concerne le programmeur, le compilateur transforme le code de haut niveau en IL. Il n'y a pas while(ou for) de boucles dans IL, seulement des étiquettes et des gotos.
Pavel Minaev le

1
voir la réponse de Pierre-Alain Vigeant.
serhio

3
Sa réponse peut être mieux reformulée comme simplement "le compilateur génère une IL identique pour les deux" (vous ne savez pas vraiment si et quand il transforme quoi que ce soit au niveau AST, et c'est un détail d'implémentation dans tous les cas). Dans tous les cas, cela n'explique pas pourquoi "ça ne vaut pas la peine dans .NET". Il en va de même pour C ++, Java ...
Pavel Minaev

6

Personnellement, je préfère l' for (;;)idiome (venant d'un point de vue C / C ++). Bien que je convienne que le while (true)est plus lisible dans un sens (et c'est ce que j'ai utilisé à l'époque même en C / C ++), je me suis tourné vers l'utilisation de l' foridiome parce que:

  • ça se démarque

Je pense que le fait qu'une boucle ne se termine pas (de manière normale) vaut la peine d'être `` appelé '', et je pense que cela le for (;;)fait un peu plus.


enfin, en utilisant cela, nous attendrons un peu plus que les programmes se compilent (compile la transformation à partir de for => while)
serhio

3
@serhio: Pas vraiment. Cela ne le transforme pas de forà while. Pour les deux for (;;){}et while (true){}, il génère un nouveau while(true){}code. Voyez cette réponse .
wchargin

6

Le livre original K&R pour C, à partir duquel C # peut retracer son ascendance, recommandé

for (;;) ...

pour des boucles infinies. Il est sans ambiguïté, facile à lire et a une longue et noble histoire derrière lui.

Addendum (février 2017)

Bien sûr, si vous pensez que cette forme en boucle (ou toute autre forme) est trop cryptique, vous pouvez toujours simplement ajouter un commentaire .

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

Ou:

for (;;)    // Loop forever
    ...

1
oui, mais c'est pour C, pas pour C #.
serhio

1
Cela fonctionne en C #. Et le langage C # a été dérivé (indirectement) de C.
David R Tribble

4
8 ans plus tard, vous avez décidé de mettre à jour votre réponse. Nice
Metoniem

4

Ce ne devrait while(true)pas être le cas while(1), c'est donc while(1)incorrect en C #, oui;)


3

Alternativement, on pourrait dire qu'avoir une boucle infinie est normalement une mauvaise pratique de toute façon, car elle nécessite une condition de sortie à moins que l'application ne fonctionne vraiment pour toujours. Cependant, s'il s'agit d'un missile de croisière, j'accepterai qu'une condition de sortie explicite ne soit pas nécessaire.

Bien que j'aime celui-ci:

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

2
-1: tout le monde ne comprendra pas votre "boucle infinie" en lisant le code, peut-être que quelqu'un pourrait penser que c'est un bogue et essayer de le "corriger" ...
serhio

En C #, f < 16777217fc'est toujours false... donc cela ne boucle jamais.
NetMage

2

Je préfère un code un peu plus «alphabétisé». Je suis beaucoup plus susceptible de faire quelque chose comme ça dans la pratique:

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

    shouldContinue = CheckSomething();
}

1
Pouah. En fait, c'est une do ... while()boucle déguisée. Cela m'a juste pris quelques secondes pour voir ça. Si vous aviez écrit une do ... while()boucle, elle aurait été immédiatement claire. -1
sbi

pourquoi perdre du temps et des ressources à déclarer une variable alors que vous pouvez utiliser while (true)? Cela n'a pas de sens à mon avis
waqasahmed

Je le trouve plus lisible, surtout si vous pouvez attacher un drapeau significatif spécifique, par exemple "while (! This.canceled)" pour indiquer que l'annulation est le seul moyen d'arrêter la boucle, "while (! ProcessExited)" pour indiquer la boucle devrait fonctionner jusqu'à ce qu'un processus externe disparaisse, etc. Il y a beaucoup de choses qui "gaspillent des ressources" qui sont absolument la bonne chose à faire au nom de la facilité de maintenance ou de lisibilité. "while (true)" n'est pas si mal que ça, mais d'après mon expérience, il y a généralement une meilleure façon.
bobbymcr

1
+1. Dans la plupart des cas, une véritable boucle infinie n'est pas ce qui se passe réellement, et vous avez une condition où vous souhaiteriez vous arrêter (par exemple lorsque l'imprimante est en feu).
Lie Ryan

1
… Auquel cas vous devriez utiliser break.
Ry-

2

Même moi, je dis aussi que celui ci-dessous est meilleur :)

while(true)
{

}

1

Si vous jouez au code-golf, je suggérerais for(;;). Au-delà, while(true)a le même sens et semble plus intuitif. Dans tous les cas, la plupart des codeurs comprendront probablement les deux variantes, donc cela n'a pas vraiment d'importance. Utilisez ce qui est le plus confortable.


2
si vous jouez au golf, C # est de toute façon le mauvais langage.
SingleNegationElimination

1

En termes de lisibilité du code while(true)dans n'importe quelle langue, je pense que cela a plus de sens. En ce qui concerne la façon dont l'ordinateur le voit, il ne devrait vraiment pas y avoir de différence dans la société actuelle de compilateurs et d'interprètes très efficaces.

S'il y a une différence de performance à avoir, je suis sûr que la traduction vers MSIL sera optimisée. Vous pouvez vérifier cela si vous le souhaitez vraiment.


1

La seule raison que je dirais for(;;)est due aux limitations de CodeDom (alors que les boucles ne peuvent pas être déclarées à l'aide de CodeDom et que les boucles for sont considérées comme la forme la plus générale en tant que boucle d'itération).

C'est une raison assez vague de choisir ceci autre que le fait que l' forimplémentation de la boucle peut être utilisée à la fois pour le code normal et le code généré par CodeDom. Autrement dit, cela peut être plus standard.

En guise de note, vous pouvez utiliser des extraits de code pour créer une whileboucle, mais la boucle entière devrait être un extrait de code ...


1

Les deux ont la même fonction, mais les gens préfèrent généralement while(true). C'est facile à lire et à comprendre ...


0

Toute expression qui renvoie toujours vrai doit être OK pour la boucle while.

Exemple:

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

Pourquoi voudriez-vous le forcer à faire une comparaison comme 1 = 1 alors que true fonctionne aussi bien? Utiliser une expression calculée semble aussi stupide que de définir une constante telle que NUMBER_OF_ARMS = 598-3596;
JohnFx

C'est un exemple pour la réponse indiquée avant le code :)
George
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.