C # loop - break เทียบกับดำเนินการต่อ


797

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

ตัวอย่าง:

foreach (DataRow row in myTable.Rows)
{
    if (someConditionEvalsToTrue)
    {
        break; //what's the difference between this and continue ?
        //continue;
    }
}

2
โพสต์บล็อกที่มีจุดสุดยอดด้านล่างadamthings.com/post/2012/07/26/…
Adam

8
continue;จะหยุดการประมวลผลปัจจุบันrowและดำเนินการต่อ rowจากการรวบรวมต่อไป ในทางกลับกันbreak;จะออกจากforeachข้อความอย่างสมบูรณ์และแถวที่เหลือจะไม่ถูกประมวลผล
Jeppe Stig Nielsen

คำตอบ:


1500

breakจะออกจากลูปทั้งหมดcontinueเพียงแค่ข้ามการวนซ้ำปัจจุบัน

ตัวอย่างเช่น:

for (int i = 0; i < 10; i++) {
    if (i == 0) {
        break;
    }

    DoSomeThingWith(i);
}

ตัวแบ่งจะทำให้ลูปออกจากการทำซ้ำครั้งแรก - DoSomeThingWithจะไม่ถูกดำเนินการ ที่นี่:

for (int i = 0; i < 10; i++) {
    if(i == 0) {
        continue;
    }

    DoSomeThingWith(i);
}

จะไม่ดำเนินการDoSomeThingWithสำหรับi = 0แต่วงที่จะดำเนินการต่อไปและDoSomeThingWithจะถูกดำเนินการสำหรับการi = 1i = 9


2
ทำไมวงเล็บปีกกาของพวกเขาถึงยังคงดำเนินต่อไป - ฉันรู้ว่ามันใช้งานได้โดยไม่มีพวกเขา แต่ทำไม?
George Willcox

52
@GeorgeWillcox น้องที่อายุน้อยกว่าตัวเองที่โง่กว่านั้นยังไม่ได้เรียนรู้คุณค่าของการใช้เครื่องมือจัดฟันเสมอ (พวกมันเป็นตัวเลือกใน C # สำหรับคำสั่งเดียว แต่ไม่ได้ใส่ไว้ทำให้ง่ายต่อการแนะนำบั๊กในภายหลังนอกจากนี้โปรดดูprogrammers.stackexchange.com/a/16530/6342 )
Michael Stum

386

วิธีที่ง่ายมากที่จะเข้าใจสิ่งนี้คือการวางคำว่า "วน" หลังจากคำหลักแต่ละคำ คำศัพท์นี้สมเหตุสมผลถ้าพวกเขาอ่านเหมือนวลีประจำวัน

break วนซ้ำ - ลูปหักและหยุด

continue วนซ้ำ - วนรอบดำเนินการต่อด้วยการวนซ้ำครั้งถัดไป


105

breakทำให้ตัวนับโปรแกรมกระโดดออกจากขอบเขตของลูปด้านในสุด

for(i = 0; i < 10; i++)
{
    if(i == 2)
        break;
}

ทำงานเช่นนี้

for(i = 0; i < 10; i++)
{
    if(i == 2)
        goto BREAK;
}
BREAK:;

ยังคงกระโดดไปยังจุดสิ้นสุดของวง ใน a for loop ให้ข้ามไปยังนิพจน์ส่วนเพิ่ม

for(i = 0; i < 10; i++)
{
    if(i == 2)
        continue;

    printf("%d", i);
}

ทำงานเช่นนี้

for(i = 0; i < 10; i++)
{
    if(i == 2)
        goto CONTINUE;

    printf("%d", i);

    CONTINUE:;
}

2
ฉันสังเกตเห็นว่ามีลูปมากมายที่นี่เพียงใช้forลูปมาตรฐานแต่จะใช้ได้กับwhileลูปทดสอบทั้งก่อนและโพสต์หรือไม่ gotoนำไปสู่สัญกรณ์ให้เชื่อเช่นนั้น แต่ต้องตรวจสอบบาง
Daniel Park

1
@Daniel สำหรับวงวนในขณะที่คุณสามารถใช้ BREAK และดำเนินต่อไปได้อย่างไม่มีปัญหา
Amila

@DanielPark สำหรับทั้งwhile("ทดสอบล่วงหน้า") และdo- while("ทดสอบหลังการทดสอบ") หลังจากcontinue;คำสั่งถูกพบสิ่งต่อไปที่จะเกิดขึ้นคือเงื่อนไขของลูปจะได้รับการประเมินเพื่อตัดสินใจว่าจะวนซ้ำเพิ่มเติมหรือไม่ ของหลักสูตรที่มีbreak;สภาพ loop จะไม่ตรวจสอบห่วงจะออกเพียงอย่างสมบูรณ์ ดังนั้นการgotoเปรียบเทียบจึงเป็นสิ่งที่ดีสำหรับการทำความเข้าใจด้านนี้เช่นกัน
Jeppe Stig Nielsen

37

ฉันเคยสับสนอยู่เสมอว่าควรหยุดพักหรือทำต่อไป นี่คือสิ่งที่ช่วยให้ฉันจำได้:

ควรใช้ break vs ต่อเมื่อใด

  1. แตก - เหมือนเลิกกัน มันเศร้าพวกคุณกำลังจากกัน ออกจากลูปแล้ว

หยุดพัก

  1. ดำเนินการต่อ - หมายความว่าคุณจะได้พักผ่อนในวันนี้และคัดออกทั้งหมดในวันพรุ่งนี้ (เช่นข้ามการทำซ้ำปัจจุบัน)!

ต่อ


จะแบ่งปันสิ่งนี้กับคู่ของฉัน อาจเป็นดำเนินการต่อควรเปลี่ยนชื่อเป็น GetOverIt และควรเปลี่ยนชื่อตัวแบ่งเป็น MoveOnForward ไม่น่าแปลกใจที่เราถูกเรียกว่า geeks Break มีเหตุผลยังไงบ้าง? มันฟังดูเป็นการทำลาย และสิ่งที่ต้องเพิ่มคือ - STOP หรือ EndIt ที่ดียิ่งขึ้น - จะแก้ไขข้อบกพร่องมากมายและทำให้ C-sharp คมอย่างแท้จริง
Mike

เข้าสู่น้ำท่วมอีกครั้งทริปเก่ามันกลับมาแล้วดังนั้นฉันจึงทำผิดพลาดครั้งใหญ่ลองดูอีกครั้งทางของฉัน
Talal Zahid

@ TalalZahid ฉันไม่เข้าใจ?
BKSpurgeon


20

มีมากกว่าคนไม่กี่คนที่ไม่ชอบและbreak continueการร้องเรียนล่าสุดที่ฉันเห็นเกี่ยวกับพวกเขานั้นอยู่ในJavaScript: The Good Partsโดย Douglas Crockford แต่ผมพบว่าบางครั้งการใช้ของพวกเขาจริงๆช่วยลดความยุ่งยากสิ่งโดยเฉพาะอย่างยิ่งถ้าภาษาของคุณไม่ได้รวมdo-whileหรือdo-untilรูปแบบของวง

ฉันมักจะใช้breakในลูปที่กำลังค้นหารายการสำหรับบางสิ่งบางอย่าง เมื่อพบว่าไม่มีประเด็นใดที่จะดำเนินการต่อไปดังนั้นคุณอาจเลิกเช่นกัน

ฉันใช้continueเมื่อทำสิ่งที่มีองค์ประกอบส่วนใหญ่ของรายการ แต่ก็ยังต้องการข้ามบางส่วน

breakคำสั่งยังมาพร้อมประโยชน์เมื่อการเลือกตั้งสำหรับการตอบสนองที่ถูกต้องจากคนหรือบางสิ่งบางอย่าง แทน:

Ask a question
While the answer is invalid:
    Ask the question

คุณสามารถกำจัดความซ้ำซ้อนและใช้:

While True:
    Ask a question
    If the answer is valid:
        break

การdo-untilวนซ้ำที่ฉันพูดถึงก่อนหน้านี้เป็นทางออกที่ดีกว่าสำหรับปัญหาเฉพาะนั้น:

Do:
    Ask a question
    Until the answer is valid

ไม่มีการทำซ้ำและไม่breakจำเป็นเช่นกัน


13

ทุกคนให้คำอธิบายที่ดีมาก ฉันยังคงโพสต์คำตอบของฉันเพียงเพื่อให้ตัวอย่างถ้าสามารถช่วยได้

// break statement
for (int i = 0; i < 5; i++) {
    if (i == 3) {
        break; // It will force to come out from the loop
    }

    lblDisplay.Text = lblDisplay.Text + i + "[Printed] ";
}

นี่คือผลลัพธ์:

0 [พิมพ์] 1 [พิมพ์] 2 [ถูกพิมพ์]

ดังนั้น 3 [พิมพ์] & 4 [พิมพ์] จะไม่ปรากฏเนื่องจากมีการแตกเมื่อ i == 3

//continue statement
for (int i = 0; i < 5; i++) {
    if (i == 3) {
        continue; // It will take the control to start point of loop
    }

    lblDisplay.Text = lblDisplay.Text + i + "[Printed] ";
}

นี่คือผลลัพธ์:

0 [พิมพ์] 1 [พิมพ์] 2 [พิมพ์] 4 [พิมพ์]

ดังนั้น 3 [ที่พิมพ์] จะไม่ปรากฏขึ้นเนื่องจากมีการดำเนินการต่อเมื่อ i == 3


7

หยุดพัก

ทำลายกองกำลังห่วงเพื่อออกทันที

ต่อ

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


1
ดำเนินการต่อการตรวจสอบสภาพห่วงมากเกินไป :)
Grantly

1
Continueไม่ได้เป็นตรงข้ามของbreak, breakหยุดวงcontinueหยุดย้ำปัจจุบัน
สตีเวน

6

คำตอบง่ายๆ:

ทำลายออกจากวงทันที
ยังคงเริ่มต้นการประมวลผลรายการถัดไป (หากมีอยู่ให้ไปที่บรรทัดการประเมินของสำหรับ / ขณะ)


6

ตามตัวอย่าง

foreach(var i in Enumerable.Range(1,3))
{
    Console.WriteLine(i);
}

พิมพ์ 1, 2, 3 (แยกบรรทัด)

เพิ่มเงื่อนไขการพักที่ i = 2

foreach(var i in Enumerable.Range(1,3))
{
    if (i == 2)
        break;

    Console.WriteLine(i);
}

ตอนนี้ลูปจะพิมพ์ 1 และหยุด

แทนที่ตัวแบ่งด้วยการดำเนินการต่อ

foreach(var i in Enumerable.Range(1,3))
{
    if (i == 2)
        continue;

    Console.WriteLine(i);
}

ตอนนี้จะวนซ้ำพิมพ์ 1 และ 3 (ข้าม 2)

ดังนั้นbreakหยุดลูปในขณะที่continueข้ามไปที่ซ้ำต่อไป


5

ทับทิมน่าเสียดายที่แตกต่างกันเล็กน้อย PS: ความทรงจำของฉันค่อนข้างขุ่นมัวในเรื่องนี้ดังนั้นขอโทษถ้าฉันผิด

แทนที่จะหยุดพัก / ต่อมันมีเบรค / ต่อไปซึ่งมีพฤติกรรมเหมือนกันในแง่ของลูป

ลูป (เหมือนทุกอย่างอื่น) เป็นนิพจน์และ "คืน" สิ่งสุดท้ายที่พวกเขาทำ เวลาส่วนใหญ่การรับค่าส่งคืนจากลูปนั้นไม่มีจุดหมายดังนั้นทุกคนจะทำเช่นนี้

a = 5
while a < 10
    a + 1
end

อย่างไรก็ตามคุณสามารถทำได้

a = 5
b = while a < 10
    a + 1
end # b is now 10

อย่างไรก็ตามรหัสทับทิมจำนวนมาก 'เลียนแบบ' ลูปโดยใช้บล็อก ตัวอย่างที่ยอมรับได้คือ

10.times do |x|
    puts x
end

เนื่องจากเป็นเรื่องปกติที่คนทั่วไปต้องการทำสิ่งต่าง ๆ ด้วยผลลัพธ์ของบล็อกนี่จึงเป็นจุดที่ยุ่งเหยิง break / next หมายถึงสิ่งต่าง ๆ ในบริบทของบล็อก

ตัวแบ่งจะกระโดดจากรหัสที่เรียกว่าบล็อก

ถัดไปจะข้ามรหัสที่เหลือในบล็อกและ 'ส่งคืน' สิ่งที่คุณระบุให้ผู้โทรของบล็อก สิ่งนี้ไม่สมเหตุสมผลหากไม่มีตัวอย่าง

def timesten
    10.times{ |t| puts yield t }
end


timesten do |x|
   x * 2
end
# will print
2
4
6
8 ... and so on


timesten do |x|
    break
    x * 2
end
# won't print anything. The break jumps out of the timesten function entirely, and the call to `puts` inside it gets skipped

timesten do |x|
    break 5
    x * 2
end
# This is the same as above. it's "returning" 5, but nobody is catching it. If you did a = timesten... then a would get assigned to 5

timesten do |x|
    next 5
    x * 2
end 
# this would print
5
5
5 ... and so on, because 'next 5' skips the 'x * 2' and 'returns' 5.

ใช่แล้ว Ruby นั้นยอดเยี่ยม แต่มีบางมุมที่แย่มาก นี่เป็นครั้งที่สองที่แย่ที่สุดที่ฉันเคยเห็นในปีที่ผ่านมาของการใช้ :-)


5

โปรดแจ้งให้ฉันทราบอย่างชัดเจน: โปรดทราบว่าการเพิ่มตัวแบ่งหรือไม่ดำเนินการต่อจะทำให้โปรแกรมของคุณกลับมาทำงานต่อได้ เช่นฉันติดกับข้อผิดพลาดบางอย่างจากนั้นหลังจากเข้าสู่ระบบฉันต้องการที่จะดำเนินการต่อและมีงานโค้ดเพิ่มเติมระหว่างแถวถัดไปดังนั้นฉันจึงปล่อยให้มันผ่านไป


3

เมื่อต้องการแยกออกจากลูป foreach อย่างสมบูรณ์จะใช้การแบ่ง

เพื่อไปยังย้ำต่อไปในวงที่ยังคงถูกนำมาใช้;

ตัวแบ่งมีประโยชน์ถ้าคุณวนลูปผ่านชุดของวัตถุ (เช่นแถวใน Datatable) และคุณกำลังค้นหาคู่ที่เฉพาะเจาะจงเมื่อคุณพบว่าการจับคู่นั้นไม่จำเป็นต้องผ่านแถวที่เหลือต่อไปดังนั้นคุณต้องการทำลาย ออก.

ทำต่อไปจะมีประโยชน์เมื่อคุณทำสิ่งที่คุณต้องการในการวนซ้ำแบบวนซ้ำ ปกติคุณจะต้องดำเนินการต่อไปหลังจากที่ถ้า


2

หากคุณไม่ต้องการใช้ตัวแบ่งคุณเพียงเพิ่มมูลค่าของ I ในลักษณะที่ทำให้เงื่อนไขการทำซ้ำเป็นเท็จและลูปจะไม่ทำงานในการทำซ้ำครั้งถัดไป

for(int i = 0; i < list.Count; i++){
   if(i == 5)
    i = list.Count;  //it will make "i<list.Count" false and loop will exit
}

0

สำหรับภาษาอื่น ๆ :

'VB
For i=0 To 10
   If i=5 then Exit For '= break in C#;
   'Do Something for i<5
next

For i=0 To 10
   If i=5 then Continue For '= continue in C#
   'Do Something for i<>5...
Next
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.