C # infinite loop ที่ถูกต้องคืออะไรสำหรับ (;;) หรือ while (true)? [ปิด]


97

ย้อนกลับไปในวัน C / C ++ ของฉันเขียนโค้ด "ลูปไม่มีที่สิ้นสุด" เป็น

while (true)

รู้สึกเป็นธรรมชาติมากขึ้นและดูเหมือนชัดเจนสำหรับฉันเมื่อเทียบกับ

for (;;)

การเผชิญหน้ากับPC-lintในช่วงปลายทศวรรษ 1980 และการอภิปรายแนวทางปฏิบัติที่ดีที่สุดในภายหลังทำให้ฉันมีนิสัยนี้ ฉันได้เขียนรหัสลูปโดยใช้forคำสั่งควบคุม วันนี้เป็นครั้งแรกในระยะเวลาอันยาวนานและบางทีความต้องการครั้งแรกของฉันสำหรับการวนซ้ำที่ไม่มีที่สิ้นสุดในฐานะนักพัฒนา C # ฉันกำลังเผชิญกับสถานการณ์เดียวกัน หนึ่งในนั้นถูกต้องหรือไม่?


5
คำตอบที่เหมือนกันสี่คำในเวลาไม่ถึงสองนาที ไม่เลว.
Jon B

5
คุณสามารถหลีกเลี่ยงข้อโต้แย้งทางศาสนาทั้งหมดได้โดยการคลายการวนซ้ำที่ไม่สิ้นสุด ไม่ควรใช้เวลานาน ...
Stephen Darlington

7
เพียงแค่อยากรู้อยากเห็น: เหตุใด (;;) จึงดีกว่าใน C / C ++
Vilx-

6
@Vilx อย่างที่ฉันจำได้คอมไพเลอร์เก่าเคยเขียนโค้ดที่มีประสิทธิภาพมากขึ้นด้วย for (;;) มากกว่า while (1) ฉันแน่ใจว่าคอมไพเลอร์สมัยใหม่ที่เหมาะสมจะส่งออกโค้ดที่เหมือนกันมาก
Stephen Darlington

4
จากข้อคิดเห็นของ Stephen และ Serhio: 1. while(true)ต้องมีเงื่อนไข for(;;)ดังนั้นจึงเป็นตัวแทนที่ดีกว่าสำหรับลูปที่ไม่มีที่สิ้นสุดซึ่งทำซ้ำโดยไม่มีเงื่อนไข 2. คอมไพเลอร์ที่ไม่ได้เพิ่มประสิทธิภาพเก่าอาจประเมิน(true)ตามที่วนซ้ำ 3. C เป็นภาษาที่เรียบง่ายตั้งแต่สมัยของเทเลไทป์เทอร์มินัล 300 บอดและชื่อตัวแปร 1 ตัวอักษร ในสภาพแวดล้อมที่ทุกคนนับจังหวะสำคัญไม่น้อยที่สั้นกว่าfor(;;) while(true)
Richard Dingwall

คำตอบ:


124
while(true)
{

}

เป็นสิ่งที่ฉันใช้เสมอและสิ่งที่ฉันเคยเห็นคนอื่นใช้สำหรับลูปที่ต้องเสียด้วยตนเอง


@RSolberg - มันเป็นการสลับกันระหว่างคำตอบที่คล้ายกันทั้งสองที่เสนอภายในไม่กี่วินาทีต่อกัน ความคิดเห็นติดตามผลของอดัมทำให้ฉันยอมรับคำตอบตามการใช้งานมากกว่าแบบแผน
Bob Kaufman

1
ในขณะที่และสำหรับทั้งสองสามารถหักด้วยตนเอง
Allen Rice

2
น่าเสียดายที่คำตอบนี้ไม่ตอบคำถาม คำตอบที่ถูกต้องคือ "ถูกต้องทั้งคู่"
David R Tribble

2
@Loadmaster: ขึ้นอยู่กับคำจำกัดความของคุณว่า "ถูกต้อง" (หรือว่าคุณเป็น "ความถูกต้อง" แบบไหน)
Adam Robinson

319

คอมไพเลอร์ C # จะแปลงทั้งสองอย่าง

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

และ

while (true)
{
    // ...
}

เป็น

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

CIL สำหรับทั้งสองเหมือนกัน คนส่วนใหญ่มักwhile(true)จะอ่านและเข้าใจได้ง่ายกว่า for(;;)ค่อนข้างคลุมเครือ

ที่มา:

ฉันยุ่งกับ. NET Reflectorอีกเล็กน้อยและฉันรวบรวมลูปทั้งสองด้วย "Optimize Code" ใน Visual Studio

ลูปทั้งสองคอมไพล์เป็น (พร้อม. NET Reflector):

Label_0000:
    goto Label_0000;

แร็พเตอร์ควรโจมตีเร็ว ๆ นี้


7
ใช่เพียงตรวจสอบสองครั้งรหัส IL เดียวกันทั้งหมดนี่ควรเป็นคำตอบที่ยอมรับ IMO :)
Allen Rice

64
+1 สำหรับการอ้างอิง xkcd
Ikke

4
คอมไพเลอร์จะไม่แปลงรูปแบบคำสั่งหนึ่งไปเป็นอีกรูปแบบหนึ่ง แต่จะสร้างรหัสที่เหมือนกันสำหรับทั้งสองคำสั่ง รหัสนั้นเหมือนกับgotoคำสั่ง btw ซึ่งไม่แปลกใจเลย
David R Tribble

1
แล้ว goto จะถูกแปลเป็นคำสั่ง jmp ..
Marco M.

25
เห็นได้ชัดว่าgoto LOOPC # ไม่มีที่สิ้นสุดลูปที่ถูกต้อง :)
Dustin Getz

61

ฉันคิดว่าสิ่งนี้อาจอ่านง่ายกว่าและเป็นมาตรฐานสำหรับใช้ใน C #:

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

19
@voyager: 1 ไม่ได้ใช้แทน 'true' ใน C #
Adam Robinson

17
โปรดทราบว่าในขณะที่ (1) ไม่ถูกต้อง C #: ค่าคงที่ 1 ไม่สามารถแปลงเป็นบูลได้
Vinko Vrsalovic

4
while(1)ไม่ถูกต้องใน C # เนื่องจาก1ไม่ใช่ไฟล์bool.
Pavel Minaev

48

หอบใช้:

while (!false)
{

}

หรือตามที่jsightชี้ให้เห็นคุณอาจต้องการความแน่ใจเป็นสองเท่า:

while (!false && true)
{
}

ก่อนที่ผู้คนจะตะโกนใส่ฉันมันเป็นรหัส CIL เดียวกันทั้งหมดฉันตรวจสอบ :)


คำตอบที่ดีที่สุด
Larry

38

หากต้องการแก้ไขเรื่องตลกเก่า ๆ สองสามเรื่อง:

  1. อย่าใช้ " for (;;) {}" - มันทำให้คำสั่งดังขึ้น
  2. เว้นแต่คุณจะ " #define EVER ;;"

25
หรือ #define ever (;;)ที่คิดว่าน่าอ่านกว่า for ever {}
Chris Lutz

1
ฉันไม่คิดว่าคุณจะทำ #define ได้เลย (;;) ใน C # แต่เรื่องตลกก็ตลก :)
Allen Rice

1
อา. ฉันตั้งโปรแกรม C บน OS X ฉันไม่รู้ว่าตัวประมวลผลล่วงหน้า C # ถูกตัดตอน ฉันไม่แน่ใจด้วยซ้ำว่าฉันเริ่มอ่านคำถามนี้ได้อย่างไรฉันมี C # เป็นแท็กที่ถูกเพิกเฉย ...
Chris Lutz

ตัวประมวลผลล่วงหน้า C # ไม่ได้เป็นตัวประมวลผลล่วงหน้าอย่างน้อยก็ไม่ใช่ในแง่ของสิ่งที่ C, C ++, PL / 1 และแม้แต่ตัวประกอบมาโครให้ อนุญาตให้คุณเปิดหรือปิดการใช้งานบล็อกโค้ดโดยการกำหนด / ไม่กำหนดสัญลักษณ์ตัวประมวลผลล่วงหน้า
David R Tribble

6
หรือดีกว่า: #define forever while(true);)
Roberto Bonvallet

26

หากคุณต้องการไปโรงเรียนเก่า goto ยังรองรับใน C #:

STARTOVER:  
    //Do something
    goto STARTOVER;

สำหรับลูปที่ไม่มีที่สิ้นสุดอย่างแท้จริงนี่คือคำสั่ง go-to =)



6
ฉันเพิ่มคะแนนสิ่งนี้จากการให้คะแนนเชิงลบกลับเป็นศูนย์ แต่เป็นเพียงเพราะค่าอารมณ์ขันเท่านั้น เฮ้ลูปทั้งหมดจะถูกรวบรวมเป็น opcodes แอสเซมเบลอร์ JMP ใช่มั้ย?
David R Tribble

@Loadmaster: ขอบคุณฉันแค่โยนมันออกไปที่นั่นเป็นตัวเลือกอื่นไม่จำเป็นต้องรับรอง
JohnFx

2
@serhio: ยิ่งไปกว่านั้นคือการหลีกเลี่ยงการสร้างภาษาให้พ้นมือเพราะคุณอ่านอะไรบางอย่าง ไม่มีองค์ประกอบของภาษาใดที่ไม่ดีสามารถใช้ในทางที่ไม่ดีเท่านั้น
JohnFx

2
@serhio: ฉันเคยเห็นสิ่งที่น่ารังเกียจต่อธรรมชาติโดยใช้คำหลักทุกคำที่เป็นไปได้ ไม่ใช่องค์ประกอบของภาษา แต่เป็นโปรแกรมเมอร์ ไม่ว่าในกรณีใดก็ตามดังที่ระบุไว้ในความคิดเห็นก่อนหน้าของฉันฉันไม่ได้ให้การรับรอง ฉันแค่ใส่มันลงไปเพื่อความสมบูรณ์และอารมณ์ขัน
JohnFx


10

ในสถานการณ์ที่ฉันต้องการลูปที่ไม่มีที่สิ้นสุดที่แท้จริงฉันมักจะใช้

while(true) {...}

ดูเหมือนว่าจะแสดงเจตนาได้ดีกว่าความว่างเปล่าสำหรับคำชี้แจง


10

โดยส่วนตัวแล้วฉันชอบfor(;;)อย่างแม่นยำเสมอเพราะมันไม่มีเงื่อนไข (ตรงข้ามกับwhile (true)ที่มีจริงเสมอ) อย่างไรก็ตามนี่เป็นประเด็นที่มีลักษณะเล็กน้อยมากซึ่งฉันไม่รู้สึกว่าคุ้มค่าที่จะเถียงด้วยวิธีใด ฉันยังไม่เห็นแนวทางสไตล์ C # ที่บังคับหรือห้ามไม่ให้เข้าใกล้


ไม่คุ้มค่าใน. NET เมื่อคอมไพเลอร์เปลี่ยน (อ่านได้ไม่ดี) ของคุณโดยไม่มีเงื่อนไขในขณะที่มีเงื่อนไข
serhio

3
@serhio: โปรดอธิบายความหมายของ "compiler transforms ... in a while" เท่าที่เกี่ยวกับโปรแกรมเมอร์คอมไพลเลอร์จะแปลงรหัสระดับสูงเป็น IL ไม่มีลูปwhile(หรือfor) ใน IL มีเพียงป้ายกำกับและ gotos
Pavel Minaev

1
ดูคำตอบของ Pierre-Alain Vigeant
serhio

3
คำตอบของเขาสามารถเปลี่ยนวลีได้ดีกว่าเพียงแค่ "คอมไพเลอร์สร้าง IL ที่เหมือนกันสำหรับทั้งคู่" (คุณไม่รู้จริงๆว่ามันแปลงอะไรในระดับ AST หรือไม่และเป็นรายละเอียดการนำไปใช้ในกรณีใด ๆ ) ไม่ว่าในกรณีใดสิ่งนี้ไม่ได้อธิบายว่าทำไมจึง "ไม่คุ้มค่าใน. NET" เช่นเดียวกับ C ++, Java ...
Pavel Minaev

6

ฉันชอบfor (;;)สำนวนเป็นการส่วนตัว(มาจากมุมมอง C / C ++) ในขณะที่ฉันยอมรับว่าwhile (true)มันสามารถอ่านได้มากกว่าในแง่หนึ่ง (และเป็นสิ่งที่ฉันใช้วิธีย้อนกลับไปแม้ใน C / C ++) ฉันหันมาใช้forสำนวนเพราะ:

  • มันโดดเด่น

ฉันคิดว่าการวนซ้ำไม่ได้ยุติลง (ตามแบบปกติ) นั้นคุ้มค่าที่จะ 'เรียกร้องออกไป' และฉันคิดว่าสิ่งfor (;;)นี้จะเพิ่มขึ้นอีกเล็กน้อย


ในที่สุดโดยใช้ว่าเราจะรออีกเล็กน้อยที่โปรแกรมรวบรวม (คอมไพล์การแปลงจาก for => while)
serhio

3
@serhio: ไม่จริง มันไม่ได้เปลี่ยนจากการfor whileสำหรับทั้งสองfor (;;){}และwhile (true){}จะสร้างwhile(true){}รหัสใหม่ ดูคำตอบนี้
wchargin

6

แนะนำหนังสือK&Rต้นฉบับสำหรับ C ซึ่ง C # สามารถติดตามบรรพบุรุษได้

for (;;) ...

สำหรับลูปที่ไม่มีที่สิ้นสุด มันไม่คลุมเครืออ่านง่ายและมีประวัติอันยาวนานและสูงส่งอยู่เบื้องหลัง

ภาคผนวก (ก.พ. 2560)

แน่นอนถ้าคุณคิดว่ารูปแบบการวนซ้ำ (หรือรูปแบบอื่น ๆ ) นี้คลุมเครือเกินไปคุณสามารถเพิ่มความคิดเห็นได้ตลอดเวลา

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

หรือ:

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

1
ใช่ แต่สำหรับ C ไม่ใช่สำหรับ C #
serhio

1
ทำงานใน C # และภาษา C # ได้มา (ทางอ้อม) จาก C.
David R Tribble

4
8 ปีต่อมาคุณตัดสินใจอัปเดตคำตอบของคุณ Nice
Metoniem

4

มันควรจะเป็นwhile(true)ไม่ได้while(1)ดังนั้นwhile(1)ไม่ถูกต้องใน C # ใช่;)


3

อีกทางเลือกหนึ่งอาจกล่าวได้ว่าการมีลูปแบบไม่มีที่สิ้นสุดนั้นเป็นแนวทางปฏิบัติที่ไม่ดีอยู่แล้วเนื่องจากต้องมีเงื่อนไขการออกเว้นแต่แอปจะทำงานตลอดไป อย่างไรก็ตามหากนี่คือขีปนาวุธล่องเรือฉันจะยอมรับเงื่อนไขการออกที่ชัดเจนอาจไม่จำเป็น

แม้ว่าฉันจะชอบสิ่งนี้:

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

2
-1: ไม่ใช่ทุกคนที่จะเข้าใจ "การวนซ้ำที่ไม่สิ้นสุด" ของคุณในการอ่านโค้ดบางทีใครบางคนอาจคิดว่านี่เป็นข้อบกพร่องและพยายาม "แก้ไข" มัน ...
serhio

ใน 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)" เพื่อระบุลูป ควรดำเนินการจนกว่ากระบวนการภายนอกจะหายไป ฯลฯ มีหลายสิ่งหลายอย่างที่ "สิ้นเปลืองทรัพยากร" ซึ่งเป็นสิ่งที่ถูกต้องอย่างยิ่งที่จะทำในนามของความง่ายในการบำรุงรักษาหรืออ่านได้ "ในขณะที่ (จริง)" ไม่ได้เลวร้าย แต่จากประสบการณ์ของฉันมักจะมีวิธีที่ดีกว่า
bobbymcr

1
+1. ในกรณีส่วนใหญ่การวนซ้ำที่ไม่มีที่สิ้นสุดที่แท้จริงไม่ใช่สิ่งที่เกิดขึ้นจริงและคุณมีเงื่อนไขบางอย่างที่คุณต้องการหยุด (เช่นเมื่อเครื่องพิมพ์ลุกเป็นไฟ)
Lie Ryan

1
... breakซึ่งในกรณีนี้คุณควรใช้
Ry-


1

for(;;)หากคุณเป็นรหัสในการเล่นกอล์ฟผมจะแนะนำ นอกเหนือจากนั้นwhile(true)ยังมีความหมายเดียวกันและดูเหมือนใช้งานง่ายกว่า ไม่ว่าอย่างไรก็ตามผู้เขียนโค้ดส่วนใหญ่มักจะเข้าใจรูปแบบทั้งสองดังนั้นจึงไม่สำคัญ ใช้สิ่งที่สะดวกสบายที่สุด


2
หากคุณกำลังตีกอล์ฟ C # ก็เป็นภาษาที่ไม่ถูกต้องอยู่ดี
SingleNegationElimination

1

ในแง่ของความสามารถwhile(true)ในการอ่านโค้ดในภาษาใดก็ตามฉันรู้สึกว่ามีเหตุผลมากกว่า ในแง่ของวิธีที่คอมพิวเตอร์เห็นว่ามันไม่ควรมีความแตกต่างใด ๆ ในสังคมปัจจุบันของคอมไพเลอร์และล่ามที่มีประสิทธิภาพ

หากมีความแตกต่างด้านประสิทธิภาพฉันแน่ใจว่าการแปลเป็น MSIL จะปรับให้เหมาะสมที่สุด คุณสามารถตรวจสอบได้ว่าคุณต้องการจริงๆหรือไม่


1

เหตุผลเดียวที่ฉันบอกว่าfor(;;)เป็นเพราะข้อ จำกัด ของ CodeDom (ในขณะที่ไม่สามารถประกาศลูปโดยใช้ CodeDom และสำหรับลูปจะถูกมองว่าเป็นรูปแบบทั่วไปมากกว่าในรูปแบบการวนซ้ำ)

นี่เป็นเหตุผลที่ค่อนข้างหลวมในการเลือกสิ่งนี้นอกเหนือจากข้อเท็จจริงที่ว่าการforใช้งานลูปสามารถใช้ได้ทั้งกับรหัสปกติและรหัสที่สร้างขึ้นของ CodeDom นั่นคือสามารถมีมาตรฐานมากขึ้น

โปรดทราบว่าคุณสามารถใช้ข้อมูลโค้ดเพื่อสร้างwhileลูปได้ แต่ลูปทั้งหมดจะต้องเป็นข้อมูลโค้ด ...


1

ทั้งสองของพวกเขามีฟังก์ชันเดียวกัน while(true)แต่คนมักชอบ รู้สึกง่ายต่อการอ่านและเข้าใจ ...


0

นิพจน์ใด ๆ ที่ส่งกลับค่าจริงเสมอควรจะตกลงในขณะที่วนซ้ำ

ตัวอย่าง:

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

ทำไมคุณถึงต้องกังวลกับการบังคับให้ทำการเปรียบเทียบเช่น 1 = 1 เมื่อ true ทำงานได้ดีเช่นกัน? การใช้นิพจน์ที่คำนวณแล้วให้ความรู้สึกว่าโง่พอ ๆ กับการกำหนดค่าคงที่เช่น NUMBER_OF_ARMS = 598-3596;
JohnFx

เป็นตัวอย่างสำหรับคำตอบที่ระบุไว้ข้างหน้ารหัส :)
George
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.