Vòng lặp vô hạn trong C #, for (;;) hoặc while (true) là đúng? [đóng cửa]


97

Quay lại những ngày C / C ++ của tôi, mã hóa một "vòng lặp vô hạn" là

while (true)

cảm thấy tự nhiên hơn và dường như rõ ràng hơn đối với tôi thay vì

for (;;)

Một cuộc gặp gỡ với PC-lint vào cuối những năm 1980 và các cuộc thảo luận về các phương pháp hay nhất sau đó đã khiến tôi không còn thói quen này. Tôi đã viết mã các vòng lặp bằng cách sử dụng forcâu lệnh điều khiển. Hôm nay, lần đầu tiên sau một thời gian dài, và có lẽ lần đầu tiên tôi cần một vòng lặp vô hạn với tư cách là một nhà phát triển C #, tôi đang đối mặt với tình huống tương tự. Một trong số chúng có đúng và cái còn lại thì không?


5
Bốn câu trả lời giống hệt nhau trong vòng chưa đầy hai phút. Không tệ.
Jon B

5
Bạn có thể tránh toàn bộ tranh luận về tôn giáo bằng cách mở vòng lặp vô hạn của mình. Không nên mất nhiều thời gian ...
Stephen Darlington

7
Chỉ vì tò mò: tại sao for (;;) tốt hơn trong C / C ++?
Vilx-

6
@Vilx như tôi nhớ lại, các trình biên dịch cũ được sử dụng để viết mã hiệu quả hơn với for (;;) so với while (1). Tôi chắc chắn rằng bất kỳ trình biên dịch hiện đại nào cũng sẽ xuất ra nhiều mã giống hệt nhau.
Stephen Darlington

4
Dựa trên nhận xét của Stephen và Serhio: 1. while(true)yêu cầu một điều kiện. for(;;)do đó là cách biểu diễn tốt hơn cho các vòng lặp vô hạn lặp lại vô điều kiện. 2. Các trình biên dịch cũ chưa tối ưu hóa có thể đã thực sự đánh giá (true)khi nó lặp lại. 3. C là một ngôn ngữ tối giản từ thời của teletypes, thiết bị đầu cuối 300 baud và tên biến 1-char. Trong môi trường mà mọi hành trình phím đều được tính, for(;;)ngắn hơn một chút so với while(true).
Richard Dingwall

Câu trả lời:


124
while(true)
{

}

Luôn luôn là những gì tôi đã sử dụng và những gì tôi đã thấy những người khác sử dụng cho một vòng lặp phải được phá vỡ thủ công.


@RSolberg - đó là sự thay đổi giữa hai phản hồi tương tự được đưa ra trong vòng vài giây với nhau. Nhận xét tiếp theo của Adam khiến tôi chấp nhận câu trả lời dựa trên cách sử dụng thay vì quy ước.
Bob Kaufman

1
trong khi và cho cả hai đều có thể bị phá vỡ theo cách thủ công
Allen Rice

2
Thật không may, câu trả lời này không trả lời câu hỏi. Câu trả lời đúng là "cả hai đều đúng".
David R Tribble

2
@Loadmaster: Điều đó phụ thuộc vào định nghĩa của bạn về "đúng" (hay đúng hơn là bạn đang theo đuổi loại "đúng" nào).
Adam Robinson

314

Trình biên dịch C # sẽ biến đổi cả hai

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

while (true)
{
    // ...
}

thành

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

CIL cho cả hai đều giống nhau. Hầu hết mọi người thấy while(true)dễ đọc và dễ hiểu hơn. for(;;)khá khó hiểu.

Nguồn:

Tôi đã làm rối thêm một chút với .NET Reflector và tôi đã biên dịch cả hai vòng với "Mã tối ưu hóa" được bật trong Visual Studio.

Cả hai vòng đều biên dịch thành (với .NET Reflector):

Label_0000:
    goto Label_0000;

Raptors nên tấn công sớm.


7
yup, chỉ cần kích đúp kiểm tra, tất cả các mã IL cùng của nó, điều này sẽ là câu trả lời được chấp nhận IMO :)
Allen gạo

63
+1 cho tham chiếu xkcd
Ikke

4
Để mang tính ngữ nghĩa, trình biên dịch không biến đổi một dạng câu lệnh này thành dạng câu lệnh kia; thay vào đó, nó tạo ra mã giống hệt nhau cho cả hai câu lệnh. Mã đó giống hệt với một gotocâu lệnh, btw, không có gì ngạc nhiên.
David R Tribble

1
và sau đó goto được dịch thành hướng dẫn jmp ..
Marco M.

25
vì vậy rõ ràng goto LOOPlà vòng lặp vô hạn C # chính xác :)
Dustin Getz

61

Tôi nghĩ rằng điều này có thể dễ đọc hơn và chắc chắn là tiêu chuẩn để sử dụng trong C #:

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

19
@voyager: 1 không thay thế cho 'true' trong C #.
Adam Robinson

17
Lưu ý rằng trong khi (1) là không hợp lệ C #: Constant 1 không thể được chuyển đổi sang bool
Vinko Vrsalovic

4
while(1)không hợp lệ trong C #, vì 1không phải là a bool.
Pavel Minaev 09/09/09

47

Thở hổn hển, sử dụng:

while (!false)
{

}

HOẶC như jsight đã chỉ ra, bạn có thể muốn chắc chắn gấp đôi:

while (!false && true)
{
}

Trước khi mọi người mắng tôi, tất cả đều là mã CIL giống nhau, tôi đã kiểm tra :)


Câu trả lời hay nhất đến nay.
Larry

38

Để kể lại một vài câu chuyện cười cũ:

  1. Không sử dụng " for (;;) {}" - nó làm cho câu lệnh trở nên khó hiểu.
  2. Tất nhiên, trừ khi bạn " #define EVER ;;".

25
Hoặc #define ever (;;)mà tôi nghĩ là dễ đọc hơn. for ever {}
Chris Lutz 09/09/09

1
Tôi không nghĩ bạn có thể làm một #define bao giờ (;;) trong C #, tuy nhiên, những câu chuyện đùa là hài hước :)
Allen Rice

1
Ah. Tôi lập trình C trên OS X. Tôi không biết bộ tiền xử lý C # đã bị thiến như vậy. Tôi thậm chí không chắc chắn làm thế nào tôi bắt đầu đọc câu hỏi này, tôi có C # như một thẻ bỏ qua ...
Chris Lutz

Bộ tiền xử lý C # thực sự không phải là bộ tiền xử lý, ít nhất là không phải về những gì mà C, C ++, PL / 1, và thậm chí cả các trình lắp ráp macro cung cấp. Nó chỉ cho phép bạn bật hoặc tắt các khối mã bằng cách xác định / hủy xác định các ký hiệu tiền xử lý.
David R Tribble

6
Hoặc thậm chí tốt hơn: #define forever while(true);)
Roberto Bonvallet

26

Nếu bạn muốn học lại trường cũ, goto vẫn được hỗ trợ trong C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

Đối với một vòng lặp vô hạn thực sự, đây là lệnh bắt đầu. =)



6
Tôi đã ủng hộ điều này từ đánh giá tiêu cực trở lại 0, nhưng chỉ vì giá trị hài hước của nó. Này, tất cả các vòng lặp đều được biên dịch thành mã quang trình hợp dịch JMP, phải không?
David R Tribble

@Loadmaster: Cảm ơn, tôi chỉ ném nó ra đó như một lựa chọn khác, không nhất thiết phải tán thành nó.
JohnFx

2
@serhio: Thậm chí nhiều hơn thế là tránh cấu trúc ngôn ngữ ngoài tầm tay vì bạn đã đọc một cái gì đó ở đâu đó. Không có yếu tố ngôn ngữ nào tự nó là xấu, nó chỉ có thể được sử dụng theo những cách xấu.
JohnFx

2
@serhio: Tôi đã thấy sự ghê tởm chống lại thiên nhiên chỉ bằng mọi từ khóa có thể. Nó không phải là yếu tố ngôn ngữ, nó là lập trình viên. Trong mọi trường hợp, như đã lưu ý trong nhận xét trước đây của tôi, tôi không tán thành nó. Tôi chỉ bao gồm nó cho hoàn chỉnh và một chút hài hước.
JohnFx


10

Trong những tình huống mà tôi cần một vòng lặp vô hạn thực sự, tôi luôn sử dụng

while(true) {...}

Nó dường như thể hiện ý định tốt hơn một câu lệnh for rỗng.


10

Cá nhân tôi luôn thích for(;;)chính xác vì nó không có điều kiện (trái ngược với điều kiện while (true)luôn đúng). Tuy nhiên, đây thực sự là một điểm rất nhỏ về phong cách, mà tôi cảm thấy không đáng để tranh cãi. Tôi vẫn chưa thấy một hướng dẫn phong cách C # bắt buộc hoặc cấm một trong hai cách tiếp cận.


không có giá trị trong .NET, khi trình biên dịch biến đổi (có thể đọc được) của bạn mà không có điều kiện trong một thời gian với điều kiện.
serhio

3
@serhio: vui lòng giải thích ý bạn khi "biến đổi trình biên dịch ... trong a while". Theo như lập trình viên có liên quan, trình biên dịch chuyển đổi mã cấp cao thành IL. Không có while(hoặc for) vòng lặp trong IL, chỉ có nhãn và gotos.
Pavel Minaev

1
xem câu trả lời của Pierre-Alain Vigeant.
serhio

3
Câu trả lời của anh ấy có thể được diễn đạt lại tốt hơn đơn giản là "trình biên dịch tạo IL giống hệt nhau cho cả hai" (bạn không thực sự biết liệu nó có biến đổi bất cứ thứ gì ở cấp độ AST hay không và đó là chi tiết triển khai trong mọi trường hợp). Trong mọi trường hợp, điều này không giải thích tại sao nó "không có giá trị trong .NET". Điều tương tự cũng đúng với C ++, Java ...
Pavel Minaev

6

Cá nhân tôi thích for (;;)thành ngữ hơn (xuất phát từ quan điểm C / C ++). Mặc dù tôi đồng ý rằng nó while (true)dễ đọc hơn theo một nghĩa nào đó (và đó là những gì tôi đã sử dụng trở lại khi ngay cả trong C / C ++), tôi đã chuyển sang sử dụng forthành ngữ vì:

  • nó nổi bật

Tôi nghĩ rằng thực tế là một vòng lặp không kết thúc (theo cách thông thường) là đáng được 'gọi ra', và tôi nghĩ rằng for (;;)điều này còn nhiều hơn một chút.


cuối cùng, bằng cách sử dụng nó, chúng tôi sẽ đợi thêm một chút nữa chương trình biên dịch (biên dịch chuyển đổi từ for => while)
serhio

3
@serhio: Không hẳn. Nó không biến đổi nó từ forsang while. Đối với cả hai for (;;){}while (true){}, nó tạo ra while(true){}mã mới . Hãy xem câu trả lời này .
nạp tiền vào

6

Sách K&R gốc dành cho C, từ đó C # có thể theo dõi tổ tiên của nó, được khuyến nghị

for (;;) ...

cho các vòng lặp vô hạn. Nó rõ ràng, dễ đọc và có một lịch sử lâu dài và cao quý đằng sau nó.

Phụ lục (tháng 2 năm 2017)

Tất nhiên, nếu bạn cho rằng dạng lặp này (hoặc bất kỳ dạng nào khác) quá khó hiểu, bạn luôn có thể thêm nhận xét .

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

Hoặc là:

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

1
có, nhưng đây là cho C, không cho C #.
serhio

1
Nó hoạt động trong C #. Và ngôn ngữ C # được bắt nguồn (gián tiếp) từ C.
David R Tribble

4
8 năm sau, bạn quyết định cập nhật câu trả lời của mình. Nice
Metoniem

4

Nó phải là while(true)không while(1), vì vậy while(1)là không chính xác trong C #, vâng;)


2

Ngoài ra, người ta có thể nói việc có một vòng lặp vô hạn dù sao cũng là một việc làm không tốt, vì nó cần điều kiện thoát trừ khi ứng dụng thực sự chạy mãi mãi. Tuy nhiên, nếu đây là tên lửa hành trình, tôi sẽ chấp nhận điều kiện xuất cảnh rõ ràng có thể không bắt buộc.

Mặc dù tôi thích điều này:

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

2
-1: không phải ai cũng hiểu "vòng lặp vô hạn" của bạn khi đọc mã, có lẽ ai đó có thể nghĩ đây là một lỗi và cố gắng "sửa" nó ...
serhio

Trong C # f < 16777217fluôn luôn là false... vì vậy điều này không bao giờ lặp lại.
NetMage

2

Tôi thích mã "biết chữ" hơn một chút. Tôi có nhiều khả năng làm điều gì đó như thế này trong thực tế:

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

    shouldContinue = CheckSomething();
}

1
Ặc. Trên thực tế, đó là một do ... while()vòng lặp ngụy trang. Tôi chỉ mất vài giây để thấy điều đó. Nếu bạn viết một do ... while()vòng lặp, nó sẽ rõ ràng ngay lập tức. -1
sbi

Tại sao lại lãng phí thời gian và tài nguyên khi khai báo một biến khi bạn có thể sử dụng while (true)? Theo ý kiến ​​của tôi thì nó không hợp lý
waqasahmed

Tôi thấy nó dễ đọc hơn, đặc biệt nếu bạn có thể đính kèm một cờ có ý nghĩa cụ thể, ví dụ: "while (! This.canceled)" để chỉ ra rằng việc hủy bỏ là cách duy nhất để dừng vòng lặp, "while (! ProcessExited)" để chỉ ra vòng lặp nên chạy cho đến khi một quy trình bên ngoài biến mất, v.v. Có rất nhiều thứ được cho là "lãng phí tài nguyên" hoàn toàn là điều đúng đắn nên làm vì tính dễ bảo trì hoặc dễ đọc. "while (true)" không hẳn là tệ, nhưng theo kinh nghiệm của tôi thì thường có một cách tốt hơn.
bobbymcr

1
+1. Trong hầu hết các trường hợp, một vòng lặp vô hạn thực sự không phải là điều thực sự xảy ra và bạn có một số điều kiện mà bạn muốn dừng lại (ví dụ: khi máy in bị cháy).
Lie Ryan

1
… Trong trường hợp nào bạn nên sử dụng break.
Ry-

2

Ngay cả tôi cũng nói cái dưới đây là tốt hơn :)

while(true)
{

}

1

Nếu bạn đang chơi gôn mã, tôi sẽ đề nghị for(;;). Ngoài ra, while(true)có cùng ý nghĩa và có vẻ trực quan hơn. Ở bất kỳ mức độ nào, hầu hết các lập trình viên có thể sẽ hiểu cả hai biến thể, vì vậy nó không thực sự quan trọng. Sử dụng những gì thoải mái nhất.


2
nếu bạn đang chơi gôn thì C # là ngôn ngữ sai.
SingleNegationElimination

1

Lý do duy nhất tôi muốn nói for(;;)là do các giới hạn của CodeDom (trong khi các vòng lặp không thể được khai báo bằng CodeDom và các vòng lặp for được coi là dạng tổng quát hơn như một vòng lặp lặp lại).

Đây là một lý do khá lỏng lẻo để chọn điều này ngoài thực tế là việc fortriển khai vòng lặp có thể được sử dụng cho cả mã bình thường và mã được tạo CodeDom. Đó là, nó có thể được tiêu chuẩn hơn.

Xin lưu ý, bạn có thể sử dụng các đoạn mã để tạo một whilevòng lặp, nhưng toàn bộ vòng lặp sẽ cần phải là một đoạn ...


1

Cả hai đều có chức năng giống nhau, nhưng mọi người thường thích hơn while(true). Nó cảm thấy dễ dàng để đọc và hiểu ...


0

Bất kỳ biểu thức nào luôn trả về true sẽ là OK đối với vòng lặp while.

Thí dụ:

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

Tại sao bạn lại muốn ép nó thực hiện một phép so sánh như 1 = 1 trong khi true cũng hoạt động như vậy? Sử dụng một biểu thức được tính toán cảm thấy ngớ ngẩn như việc xác định một hằng số như NUMBER_OF_ARMS = 598-3596;
JohnFx

Đó là một ví dụ cho câu trả lời được nêu trước mã :)
George

0

Về khả năng đọc mã while(true)bằng bất kỳ ngôn ngữ nào tôi cảm thấy có ý nghĩa hơn. Về cách máy tính nhìn thấy nó thực sự không có bất kỳ sự khác biệt nào trong xã hội ngày nay của các trình biên dịch và thông dịch rất hiệu quả.

Nếu có bất kỳ sự khác biệt nào về hiệu suất, tôi chắc chắn rằng bản dịch sang MSIL sẽ được tối ưu hóa. Bạn có thể kiểm tra điều đó nếu bạn thực sự muốn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.