Qual é o loop infinito C # correto, para (;;) ou while (true)? [fechadas]


97

Nos meus tempos de C / C ++, codificar um "loop infinito" como

while (true)

parecia mais natural e parecia mais óbvio para mim do que

for (;;)

Um encontro com o PC-lint no final dos anos 1980 e as discussões subsequentes sobre as melhores práticas me quebraram desse hábito. Desde então, codifiquei os loops usando a forinstrução de controle. Hoje, pela primeira vez em muito tempo, e talvez minha primeira necessidade de um loop infinito como desenvolvedor C #, estou enfrentando a mesma situação. Um deles está correto e o outro não?


5
Quatro respostas idênticas em menos de dois minutos. Não é ruim.
Jon B,

5
Você poderia evitar todo o argumento religioso desenrolando seu ciclo infinito. Não deve demorar ...
Stephen Darlington,

7
Só por curiosidade: por que (;;) é ​​melhor em C / C ++?
Vilx-

6
@Vilx, pelo que me lembro, compiladores antigos costumavam escrever código mais eficiente com for (;;) do que while (1). Tenho certeza de que qualquer compilador moderno decente produzirá um código praticamente idêntico.
Stephen Darlington,

4
Com base nos comentários de Stephen e Serhio: 1. while(true)requer uma condição. for(;;)é, portanto, uma representação melhor para loops infinitos que se repetem incondicionalmente. 2. Compiladores antigos não otimizados podem realmente ter avaliado o (true)enquanto ele fazia um loop. 3. C é uma linguagem minimalista da época dos teletipos, terminais de 300 baud e nomes de variáveis ​​de 1 caractere. Em um ambiente onde cada toque de tecla conta, for(;;)é um pouco mais curto do que while(true).
Richard Dingwall,

Respostas:


124
while(true)
{

}

É sempre o que eu usei e o que vi outras pessoas usarem para um loop que tem que ser quebrado manualmente.


@RSolberg - foi uma disputa entre as duas respostas semelhantes oferecidas segundos uma da outra. O comentário posterior de Adam me levou a aceitar uma resposta baseada no uso, e não na convenção.
Bob Kaufman,

1
while e for podem ser quebrados manualmente
Allen Rice,

2
Infelizmente, essa resposta não responde à pergunta. A resposta correta é "ambos estão corretos".
David R Tribble

2
@Loadmaster: Isso depende da sua definição de "correto" (ou melhor, que tipo de "correção" você procura).
Adam Robinson

314

O compilador C # irá transformar ambos

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

e

while (true)
{
    // ...
}

para dentro

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

O CIL para ambos é o mesmo. A maioria das pessoas acha while(true)que é mais fácil de ler e compreender. for(;;)é bastante enigmático.

Fonte:

Eu baguncei um pouco mais com o .NET Reflector e compilei os dois loops com o "Optimize Code" ativado no Visual Studio.

Ambos os loops são compilados (com .NET Reflector):

Label_0000:
    goto Label_0000;

Raptors devem atacar em breve.


7
sim, verifiquei duas vezes, é tudo o mesmo código IL, esta deve ser a resposta aceita IMO :)
Allen Rice

63
+1 para a referência xkcd
Ikke,

4
Para ser pedante, o compilador não transforma uma forma de instrução na outra; em vez disso, ele gera código idêntico para ambas as instruções. Esse código é idêntico a uma gotoinstrução, aliás, o que não é nenhuma surpresa.
David R Tribble,

1
e então o goto é traduzido para uma instrução jmp ..
Marco M.

25
então, obviamente, goto LOOPé o loop infinito C # correto :)
Dustin Getz

61

Acho que isso pode ser mais fácil de ler e é definitivamente o padrão para uso em C #:

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

19
@voyager: 1 não é um substituto para 'true' em C #.
Adam Robinson,

17
Observe que enquanto (1) é inválido C #: Constante 1 não pode ser convertido em bool
Vinko Vrsalovic,

4
while(1)não é válido em C #, pois 1não é um bool.
Pavel Minaev,

47

Gasp, use:

while (!false)
{

}

OU, como jsight apontou, você pode querer ter certeza absoluta :

while (!false && true)
{
}

Antes que as pessoas gritem comigo, é tudo o mesmo código CIL, eu verifiquei :)


Melhor resposta de todas.
Larry

38

Para relembrar algumas piadas antigas:

  1. Não use " for (;;) {}" - isso faz a declaração chorar.
  2. A menos, claro, você " #define EVER ;;".

25
Ou o #define ever (;;)que eu acho mais legível. for ever {}
Chris Lutz,

1
Não achei que você pudesse fazer um #define ever (;;) em C #, porém, a piada é engraçada :)
Allen Rice,

1
Ah. Eu programo C no OS X. Eu não sabia que o pré-processador C # era tão castrado. Eu nem tenho certeza de como comecei a ler esta pergunta, eu tenho C # como uma tag ignorada ...
Chris Lutz

O pré-processador C # não é realmente um pré-processador, pelo menos não em termos do que C, C ++, PL / 1 e até mesmo montadores de macro fornecem. Ele apenas permite que você habilite ou desabilite blocos de código definindo / indefinindo símbolos de pré-processador.
David R Tribble,

6
Ou melhor ainda #define forever while(true)
:;

26

Se você quiser ir para a escola antiga, goto ainda é compatível com C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Para um loop verdadeiramente infinito, este é o comando go-to. =)



6
Eu votei positivamente de uma avaliação negativa de volta a zero, mas apenas por causa de seu valor humorístico. Ei, todos os loops são compilados em opcodes do assembler JMP de qualquer maneira, certo?
David R Tribble,

@Loadmaster: Obrigado, eu estava apenas lançando isso como outra opção, não necessariamente endossando.
JohnFx

2
@serhio: Ainda mais é evitar construções de linguagem fora de mão porque você leu algo em algum lugar. Nenhum elemento da linguagem por si só é ruim, só pode ser usado de maneiras ruins.
JohnFx

2
@serhio: Já vi abominações contra a natureza usando quase todas as palavras-chave possíveis. Não é o elemento da linguagem, é o programador. Em qualquer caso, conforme observado em meu comentário anterior, eu não estava endossando isso. Eu estava apenas incluindo para completar e dar um toque de humor.
JohnFx


10

Nas situações em que precisava de um verdadeiro loop infinito, sempre usei

while(true) {...}

Parece expressar melhor a intenção do que uma declaração vazia para.


10

Pessoalmente, sempre preferi for(;;)precisamente porque não tem nenhuma condição (ao contrário de while (true)que tem uma sempre verdadeira). No entanto, este é realmente um ponto de estilo muito menor, sobre o qual não acho que valha a pena discutir. Ainda estou para ver uma diretriz de estilo C # que obrigue ou proíba qualquer abordagem.


não vale a pena em .net, quando o compilador transforma seu (legível ruim) para sem condição em um tempo com condição.
serhio

3
@serhio: explique o que você quer dizer com "transformações do compilador ... em a while". No que diz respeito ao programador, o compilador transforma o código de alto nível em IL. Não há while(ou for) loops em IL, apenas rótulos e gotos.
Pavel Minaev

1
veja a resposta de Pierre-Alain Vigeant.
serhio

3
Sua resposta pode ser melhor reformulada como simplesmente "o compilador gera IL idêntico para ambos" (você realmente não sabe se e quando ele transforma algo no nível AST, e é um detalhe de implementação em qualquer caso). Em qualquer caso, isso não explica por que "não vale a pena em .NET". O mesmo também é verdadeiro para C ++, Java ...
Pavel Minaev

6

Eu pessoalmente prefiro o for (;;)idioma (vindo de um ponto de vista C / C ++). Embora eu concorde que o while (true)é mais legível em certo sentido (e é o que eu costumava usar quando ainda em C / C ++), comecei a usar o foridioma porque:

  • se destaca

Acho que o fato de um loop não terminar (de uma forma normal) vale a pena 'chamar', e acho que for (;;)faz isso um pouco mais.


finalmente, usando isso vamos esperar um pouco mais que os programas compilem (compilar transformação de para => enquanto)
serhio

3
@serhio: Na verdade, não. Não o transforma de forem while. Para ambos for (;;){}e while (true){}, ele gera um novo while(true){}código. Veja esta resposta .
wchargin

6

O livro K&R original para C, a partir do qual C # pode traçar sua ancestralidade, recomendava

for (;;) ...

para loops infinitos. É inequívoco, fácil de ler e tem uma longa e nobre história por trás dele.

Adendo (fevereiro de 2017)

Claro, se você acha que esta forma de loop (ou qualquer outra forma) é muito enigmática, você pode apenas adicionar um comentário .

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

Ou:

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

1
sim, mas isso é para C, não para C #.
serhio

1
Funciona em C #. E a linguagem C # foi derivada (indiretamente) de C.
David R Tribble

4
8 anos depois, você decidiu atualizar sua resposta. Nice
Metoniem de

4

Deve ser while(true)não while(1), então while(1)é incorreto em C #, sim;)


2

Alternativamente, pode-se dizer que ter um loop infinito normalmente é uma prática ruim, pois é necessária uma condição de saída, a menos que o aplicativo seja executado para sempre. No entanto, se isso for para um míssil de cruzeiro, aceitarei que uma condição de saída explícita pode não ser necessária.

Embora eu goste deste:

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

2
-1: nem todo mundo vai entender o seu "loop infinito" lendo o código, talvez alguém possa pensar que isso é um bug e tentar "consertá-lo" ...
serhio

Em C # f < 16777217fé sempre false... então isso nunca faz loop.
NetMage

2

Eu prefiro um código um pouco mais "letrado". Tenho muito mais probabilidade de fazer algo assim na prática:

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

    shouldContinue = CheckSomething();
}

1
Ugh. Na verdade, é um do ... while()laço disfarçado. Levei apenas alguns segundos para ver isso. Se você tivesse escrito um do ... while()loop, teria ficado claro imediatamente. -1
sbi 9/09/09

por que perder tempo e recursos declarando uma variável quando você pode usar while (true)? Não faz sentido na minha opinião
waqasahmed em

Acho que é mais legível, especialmente se você puder anexar um sinalizador significativo específico, por exemplo, "while (! This.canceled)" para indicar que o cancelamento é a única maneira de interromper o loop, "while (! ProcessExited)" para indicar o loop deve ser executado até que um processo externo desapareça, etc. Há muitas coisas que podem "desperdiçar recursos" que são absolutamente a coisa certa a fazer em nome da facilidade de manutenção ou legibilidade. "while (true)" não é tão ruim, mas em minha experiência geralmente há uma maneira melhor.
bobbymcr,

1
+1. Na maioria dos casos, um verdadeiro loop infinito não é o que realmente acontece, e você tem alguma condição em que deseja parar (por exemplo, quando a impressora está pegando fogo).
Lie Ryan

1
… Nesse caso você deve usar break.
Ry-


1

Se você está jogando golfe, eu sugiro for(;;). Além disso, while(true)tem o mesmo significado e parece mais intuitivo. De qualquer forma, a maioria dos programadores provavelmente entenderá ambas as variações, então isso realmente não importa. Use o que for mais confortável.


2
se você está jogando golfe, C # é a linguagem errada de qualquer maneira.
SingleNegationElimination

1

A única razão pela qual eu diria for(;;)é devido às limitações do CodeDom (enquanto os loops não podem ser declarados usando CodeDom e os loops for são vistos como a forma mais geral de um loop de iteração).

Esta é uma razão muito vaga para escolher isso, além do fato de for implementação loop pode ser usada tanto para código normal quanto para código gerado pelo CodeDom. Ou seja, pode ser mais padrão.

Como observação, você pode usar trechos de código para criar um whileloop, mas o loop inteiro precisa ser um trecho ...


1

Ambos têm a mesma função, mas geralmente as pessoas preferem while(true). Parece fácil de ler e entender ...


0

Qualquer expressão que sempre retorna verdadeiro deve ser OK para o loop while.

Exemplo:

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

Por que você se importaria em forçá-lo a fazer uma comparação como 1 = 1 quando true funciona tão bem? Usar uma expressão calculada parece tão bobo quanto definir uma constante como NUMBER_OF_ARMS = 598-3596;
JohnFx,

É um exemplo para a resposta dada antes do código :)
George,

0

Em termos de legibilidade do código while(true)em qualquer linguagem que eu sinta que faz mais sentido. Em termos de como o computador o vê, realmente não deveria haver nenhuma diferença na sociedade atual de compiladores e interpretadores muito eficientes.

Se houver alguma diferença de desempenho, tenho certeza de que a tradução para MSIL será otimizada. Você poderia verificar se realmente quisesse.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.