Manakah pengulangan C # yang benar, untuk (;;) atau while (true)? [Tutup]

97

Kembali ke hari-hari C / C ++ saya, mengkodekan "loop tak terbatas" sebagai

while (true)

terasa lebih alami dan tampak lebih jelas bagi saya daripada sebaliknya

for (;;)

Pertemuan dengan PC-lint di akhir 1980-an dan diskusi praktik terbaik berikutnya menghentikan kebiasaan ini. Saya telah mengkodekan loop menggunakan forpernyataan kontrol. Hari ini, untuk pertama kalinya dalam waktu yang lama, dan mungkin kebutuhan pertama saya untuk loop tak terbatas sebagai pengembang C #, saya menghadapi situasi yang sama. Apakah salah satunya benar dan yang lainnya tidak?

Bob Kaufman
sumber
5
Empat jawaban identik dalam waktu kurang dari dua menit. Tidak buruk.
Jon B
5
Anda dapat menghindari seluruh argumen religius dengan membuka gulungan lingkaran tak terbatas Anda. Seharusnya tidak lama ...
Stephen Darlington
7
Hanya ingin tahu: mengapa untuk (;;) lebih baik di C / C ++?
Vilx-
6
@Vilx seingat saya, kompiler lama biasa menulis kode yang lebih efisien dengan for (;;) daripada while (1). Saya yakin bahwa setiap kompiler modern yang layak akan menghasilkan kode yang hampir sama.
Stephen Darlington
4
Berdasarkan komentar Stephen dan Serhio: 1. while(true)membutuhkan suatu kondisi. for(;;)Oleh karena itu, representasi yang lebih baik untuk loop tak terbatas yang berulang tanpa syarat. 2. Kompiler lama yang tidak dioptimalkan mungkin sebenarnya telah mengevaluasi (true)saat ini berulang. 3. C adalah bahasa minimalis dari zaman teletipe, 300 terminal baud, dan nama variabel 1-char. Dalam lingkungan di mana setiap pukulan kunci dihitung, for(;;)cukup sedikit lebih pendek dari while(true).
Richard Dingwall

Jawaban:

124
while(true)
{

}

Selalu apa yang saya gunakan dan apa yang saya lihat orang lain gunakan untuk loop yang harus diputus secara manual.

Adam Robinson
sumber
@RSolberg - itu adalah pertarungan antara dua tanggapan serupa yang ditawarkan dalam hitungan detik satu sama lain. Komentar lanjutan Adam membuat saya menerima jawaban berdasarkan penggunaan daripada konvensi.
Bob Kaufman
1
sementara dan untuk keduanya dapat dipatahkan secara manual
Allen Rice
2
Sayangnya, jawaban ini tidak menjawab pertanyaan tersebut. Jawaban yang benar adalah "keduanya benar".
David R Tribble
2
@Loadmaster: Itu tergantung pada definisi Anda tentang "benar" (atau, lebih tepatnya, "kebenaran" seperti apa yang Anda cari).
Adam Robinson
314

Kompilator C # akan mengubah keduanya

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

dan

while (true)
{
    // ...
}

ke

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

CIL untuk keduanya sama. Kebanyakan orang merasa while(true)lebih mudah dibaca dan dipahami.for(;;)agak samar.

Sumber:

Saya mengacaukan sedikit lebih banyak dengan .NET Reflector , dan saya mengkompilasi kedua loop dengan "Optimize Code" di Visual Studio.

Kedua loop dikompilasi menjadi (dengan .NET Reflector):

Label_0000:
    goto Label_0000;

Raptor harus segera menyerang.

Pierre-Alain Vigeant
sumber
7
yup, cukup periksa lagi, semua kode IL-nya sama, ini harus menjadi jawaban yang diterima IMO :)
Allen Rice
63
1 untuk referensi xkcd
Ikke
4
Untuk menjadi pedantic, kompilator tidak mengubah satu bentuk pernyataan menjadi yang lain; sebaliknya, ini menghasilkan kode yang identik untuk kedua pernyataan. Kode itu identik dengan gotopernyataan, btw, yang tidak mengherankan.
David R Tribble
1
dan kemudian goto diterjemahkan ke dalam instruksi jmp ..
Marco M.
25
jadi jelas goto LOOPadalah C # infinite loop yang benar :)
Dustin Getz
61

Saya pikir ini mungkin lebih mudah dibaca dan jelas merupakan standar untuk digunakan di C #:

while(true)
{
   //Do My Loop Stuff
}
RSolberg
sumber
19
@voyager: 1 bukanlah pengganti 'true' di C #.
Adam Robinson
17
Perhatikan bahwa sementara (1) tidak valid C #: Konstanta 1 tidak dapat dikonversi ke bool
Vinko Vrsalovic
4
while(1)tidak valid di C #, karena 1bukan a bool.
Pavel Minaev
47

Terengah-engah, gunakan:

while (!false)
{

}

ATAU seperti yang ditunjukkan jsight , Anda mungkin ingin lebih yakin:

while (!false && true)
{
}

Sebelum orang meneriaki saya, itu semua kode CIL yang sama, saya memeriksa :)

Allen Rice
sumber
Jawaban terbaik yang pernah ada.
Larry
38

Untuk mengulangi beberapa lelucon lama:

  1. Jangan gunakan " for (;;) {}" - itu membuat pernyataan itu menangis.
  2. Kecuali, tentu saja, Anda " #define EVER ;;".
Ben Blank
sumber
25
Atau #define ever (;;)yang menurut saya lebih mudah dibaca. for ever {}
Chris Lutz
1
Saya tidak berpikir Anda bisa melakukan #define ever (;;) di C #, meskipun, leluconnya lucu :)
Allen Rice
1
Ah. Saya memprogram C pada OS X. Saya tidak tahu bahwa preprocessor C # sudah begitu dikebiri. Saya bahkan tidak yakin bagaimana saya mulai membaca pertanyaan ini, saya memiliki C # sebagai tag yang diabaikan ...
Chris Lutz
C # preprocessor sebenarnya bukan preprocessor, setidaknya tidak dalam hal apa yang disediakan oleh C, C ++, PL / 1, dan bahkan macro assembler. Ini hanya memungkinkan Anda untuk mengaktifkan atau menonaktifkan blok kode dengan menentukan / membatalkan definisi simbol praprosesor.
David R Tribble
6
Atau bahkan lebih baik #define forever while(true)
:;
26

Jika Anda ingin sekolah tua, goto masih didukung di C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Untuk loop yang benar-benar tak terbatas, ini adalah perintah masuk ke. =)

JohnFx
sumber
9
xkcd.com/292
Callum Rogers
6
Saya menaikkan suara ini dari peringkat negatif kembali ke nol, tetapi hanya karena nilai humornya. Hei, semua loop dikompilasi menjadi opcode assembler JMP, bukan?
David R Tribble
@Loadmaster: Terima kasih, saya baru saja melemparkannya ke luar sana sebagai opsi lain, belum tentu mendukungnya.
JohnFx
2
@serhio: Terlebih lagi adalah menghindari konstruksi bahasa di luar kendali karena Anda membaca sesuatu di suatu tempat. Tidak ada elemen bahasa itu sendiri yang buruk, itu hanya dapat digunakan dengan cara yang buruk.
JohnFx
2
@serhio: Saya telah melihat kekejian terhadap alam menggunakan hampir setiap kata kunci yang memungkinkan. Ini bukanlah elemen bahasa, itu adalah pemrogramnya. Bagaimanapun, seperti yang disebutkan dalam komentar saya sebelumnya, saya tidak mendukungnya. Saya hanya memasukkannya untuk kelengkapan dan sedikit humor.
JohnFx
21

Saya pikir while (true)ini sedikit lebih mudah dibaca.

Marplesoft
sumber
10

Dalam situasi di mana saya membutuhkan loop tak terbatas yang sebenarnya, saya selalu menggunakannya

while(true) {...}

Tampaknya mengekspresikan maksud lebih baik daripada pernyataan kosong untuk.

Michael Petrotta
sumber
10

Secara pribadi, saya selalu lebih suka for(;;)justru karena tidak ada syaratnya (berlawanan dengan while (true)yang selalu benar). Namun, ini benar-benar poin gaya yang sangat kecil, yang menurut saya tidak pantas untuk diperdebatkan. Saya belum melihat pedoman gaya C # yang mengamanatkan atau melarang pendekatan mana pun.

Pavel Minaev
sumber
tidak layak di NET, ketika compiler mengubah Anda (buruk dibaca) untuk tanpa syarat dalam sementara dengan kondisi.
serhio
3
@serhio: tolong jelaskan apa yang Anda maksud dengan "compiler transforms ... in a while". Sejauh menyangkut pemrogram, kompilator mengubah kode tingkat tinggi menjadi IL. Tidak ada while(atau for) loop di IL, hanya label dan gotos.
Pavel Minaev
1
lihat jawaban Pierre-Alain Vigeant.
serhio
3
Jawabannya dapat diutarakan dengan lebih baik karena hanya "kompilator menghasilkan IL yang identik untuk keduanya" (Anda tidak benar-benar tahu apakah dan kapan itu mengubah sesuatu pada tingkat AST, dan ini adalah detail implementasi dalam kasus apa pun). Bagaimanapun, ini tidak menjelaskan mengapa itu "tidak layak di .NET". Hal yang sama juga berlaku untuk C ++, Java ...
Pavel Minaev
6

Saya pribadi lebih suka for (;;)idiom (berasal dari sudut pandang C / C ++). Meskipun saya setuju bahwa the while (true)lebih mudah dibaca dalam arti tertentu (dan itulah yang saya gunakan kembali ketika bahkan di C / C ++), saya telah beralih menggunakan foridiom karena:

  • itu menonjol

Saya pikir fakta bahwa loop tidak berhenti (dengan cara normal) layak untuk 'dipanggil', dan saya pikir itu for (;;)melakukan ini sedikit lebih.

Michael Burr
sumber
akhirnya, dengan menggunakan itu kita akan menunggu lebih lama lagi bahwa program dikompilasi (kompilasi transformasi dari for => while)
serhio
3
@serhio: Tidak juga. Itu tidak mengubahnya dari formenjadi while. Untuk keduanya for (;;){}dan while (true){}, itu menghasilkan while(true){}kode baru . Lihat jawaban ini .
wchargin
6

Asli K & R buku untuk C, dari mana C # dapat melacak nenek moyang nya, dianjurkan

for (;;) ...

untuk loop tak terbatas. Ini tidak ambigu, mudah dibaca, dan memiliki sejarah panjang dan mulia di baliknya.

Addendum (Feb 2017)

Tentu saja, jika menurut Anda formulir perulangan ini (atau bentuk lainnya) terlalu samar, Anda selalu dapat menambahkan komentar .

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

Atau:

for (;;)    // Loop forever
    ...
David R Tribble
sumber
1
ya, tapi ini untuk C, bukan untuk C #.
serhio
1
Ia bekerja di C #. Dan bahasa C # diturunkan (tidak langsung) dari C.
David R Tribble
4
8 tahun kemudian Anda memutuskan untuk memperbarui jawaban Anda. Nice
Metoniem
4

Seharusnya while(true)tidak while(1), jadi while(1)salah di C #, yes;)

JRL
sumber
2

Atau, orang dapat mengatakan memiliki loop tak terbatas biasanya merupakan praktik yang buruk, karena ia memerlukan kondisi keluar kecuali jika aplikasi benar-benar berjalan selamanya. Namun, jika ini untuk rudal jelajah saya akan menerima kondisi keluar eksplisit mungkin tidak diperlukan.

Padahal saya suka yang ini:

for (float f = 16777216f; f < 16777217f; f++) { } 
Chris Chilvers
sumber
2
-1: tidak semua orang akan memahami "putaran tak terbatas" Anda saat membaca kode, mungkin seseorang akan berpikir ini adalah bug dan mencoba untuk "memperbaikinya" ...
serhio
Dalam C # f < 16777217fselalu false... jadi ini tidak pernah berulang.
NetMage
2

Saya lebih suka kode yang sedikit lebih "melek". Saya lebih cenderung melakukan hal seperti ini dalam praktiknya:

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

    shouldContinue = CheckSomething();
}
bobbymcr.dll
sumber
1
Ugh. Sebenarnya, itu adalah do ... while()lingkaran terselubung. Saya hanya butuh beberapa detik untuk melihatnya. Seandainya Anda menulis satu do ... while()lingkaran, itu akan segera menjadi jelas. -1
sbi
mengapa membuang-buang waktu dan sumber daya dengan mendeklarasikan variabel ketika Anda dapat menggunakan while (true)? Tidak masuk akal menurut saya
waqasahmed
Saya merasa lebih mudah dibaca, terutama jika Anda dapat melampirkan bendera bermakna tertentu, misalnya "while (! This.canceled)" untuk menunjukkan bahwa pembatalan adalah satu-satunya cara untuk menghentikan pengulangan, "while (! ProcessExited)" untuk menunjukkan pengulangan harus dijalankan sampai proses eksternal hilang, dll. Ada banyak hal yang bisa dibilang "menyia-nyiakan sumber daya" yang benar-benar benar untuk dilakukan atas nama kemudahan pemeliharaan atau keterbacaan. "sementara (benar)" tidak terlalu buruk, tetapi menurut pengalaman saya biasanya ada cara yang lebih baik.
bobbymcr
1
+1. Dalam kebanyakan kasus, loop infinite sebenarnya bukanlah yang sebenarnya terjadi, dan Anda memiliki beberapa kondisi di mana Anda ingin berhenti (misalnya saat printer terbakar).
Lie Ryan
1
… Dalam hal ini Anda harus menggunakan break.
Ry-
2

Bahkan saya juga mengatakan yang di bawah ini lebih baik :)

while(true)
{

}
anishMarokey
sumber
1

Jika Anda sedang bermain kode golf, saya sarankan for(;;). Di luar itu, while(true)memiliki arti yang sama dan terkesan lebih intuitif. Bagaimanapun, sebagian besar pembuat kode kemungkinan akan memahami kedua variasi, jadi itu tidak terlalu penting. Gunakan apa yang paling nyaman.

sobellian
sumber
2
jika Anda bermain golf maka C # adalah bahasa yang salah.
SingleNegationElimination
1

Satu-satunya alasan yang saya katakan for(;;)adalah karena keterbatasan CodeDom (sementara loop tidak dapat dideklarasikan menggunakan CodeDom dan for loop dilihat sebagai bentuk yang lebih umum sebagai loop iterasi).

Ini adalah alasan yang cukup longgar untuk memilih ini selain fakta bahwa forimplementasi loop dapat digunakan untuk kode normal dan kode yang dihasilkan CodeDom. Artinya, bisa lebih standar.

Sebagai catatan, Anda dapat menggunakan cuplikan kode untuk membuat whileloop, tetapi keseluruhan loop harus berupa cuplikan ...

Tandai Synowiec
sumber
1

Keduanya memiliki fungsi yang sama, tetapi orang pada umumnya lebih suka while(true). Rasanya mudah dibaca dan dimengerti ...

abhinav
sumber
0

Setiap ekspresi yang selalu mengembalikan nilai true harus OK untuk while loop.

Contoh:

1==1 //Just an example for the text stated before 
true
George
sumber
Mengapa Anda repot-repot memaksanya melakukan perbandingan seperti 1 = 1 ketika true berfungsi dengan baik? Menggunakan ekspresi kalkulasi terasa konyol seperti mendefinisikan konstanta seperti NUMBER_OF_ARMS = 598-3596;
JohnFx
Ini adalah contoh untuk jawaban yang dinyatakan sebelum kode :)
George
0

Dalam hal keterbacaan kode while(true) dalam bahasa apa pun yang menurut saya lebih masuk akal. Dalam hal bagaimana komputer melihatnya, seharusnya tidak ada perbedaan dalam masyarakat saat ini tentang kompiler dan juru bahasa yang sangat efisien.

Jika ada perbedaan kinerja yang bisa didapat, saya yakin terjemahan ke MSIL akan dioptimalkan. Anda dapat memeriksanya jika Anda benar-benar menginginkannya.

Chris
sumber