เหตุใดคำสั่ง 'ดำเนินการต่อ' จึงไม่สามารถอยู่ในบล็อก 'ในที่สุด' ได้?


107

ฉันไม่มีปัญหา ฉันแค่อยากรู้ ลองนึกภาพสถานการณ์ต่อไปนี้:

foreach (var foo in list)
{
    try
    {
         //Some code
    }
    catch (Exception)
    {
        //Some more code
    }
    finally
    {
        continue;
    }
}

สิ่งนี้จะไม่คอมไพล์เนื่องจากทำให้เกิดข้อผิดพลาดของคอมไพเลอร์ CS0157 :

การควบคุมไม่สามารถออกจากเนื้อความของประโยคสุดท้ายได้

ทำไม?


7
ดังนั้น. แค่สงสัย. ถ้ามันสมเหตุสมผลกับคุณว่าทำไมมันถึงไม่คอมไพล์ทำไมคุณถึงต้องการให้ใครสักคนอธิบายสิ่งที่สมเหตุสมผลอยู่แล้ว? =)
J. Steen

14
ทำไมคุณต้องcontinue;อยู่ในfinallyบล็อก? ไม่เหมือนกับcontinue;หลังtry -- catchบล็อก?
bansi

6
@ J.Steen ไม่ฉันรู้ว่าfinally/continueนี่เป็นข้อ จำกัด ของคอมไพเลอร์ C # :-) ฉันก็อยากรู้เหตุผลของข้อ จำกัด นี้เหมือนกัน
xanatos

5
@xanatos - ในทางเทคนิคมันเป็นข้อ จำกัด ของ CIL ที่อยู่เบื้องหลัง จากข้อมูลจำเพาะของภาษา : "การถ่ายโอนการควบคุมไม่ได้รับอนุญาตให้เข้าสู่ตัวจัดการการจับหรือในที่สุดอนุประโยคยกเว้นผ่านกลไกการจัดการข้อยกเว้น" และ "การควบคุมการถ่ายโอนออกจากพื้นที่ที่มีการป้องกันจะได้รับอนุญาตผ่านคำสั่งยกเว้นเท่านั้น (leave, end.filter, end.catch หรือ end.finally)" brครอบครัวของคำแนะนำสาขาไม่สามารถบรรลุเป้าหมายนี้
ไม่ลงนาม

1
@Unsigned: มันเป็นข้อ จำกัด ที่ดีเช่นกันปล่อยให้มันแปลกประหลาด :)
user7116

คำตอบ:


150

finallyบล็อกจะทำงานไม่ว่าจะมีข้อยกเว้นหรือไม่ก็ตาม หากเกิดข้อยกเว้นขึ้นห่าจะcontinueทำอย่างไร? คุณไม่สามารถดำเนินการลูปต่อไปได้เนื่องจากข้อยกเว้นที่ไม่ถูกจับจะโอนการควบคุมไปยังฟังก์ชันอื่น

แม้ว่าจะไม่มีข้อยกเว้นเกิดขึ้น แต่finallyจะทำงานเมื่อคำสั่งการถ่ายโอนการควบคุมอื่น ๆ ภายในการรันบล็อก try / catch เช่น a returnซึ่งทำให้เกิดปัญหาเดียวกัน

ในระยะสั้นด้วยความหมายของfinallyมันไม่สมเหตุสมผลที่จะอนุญาตให้โอนการควบคุมจากภายในfinallyบล็อกไปยังด้านนอกของมัน

การสนับสนุนสิ่งนี้ด้วยความหมายทางเลือกบางอย่างอาจทำให้สับสนมากกว่าเป็นประโยชน์เนื่องจากมีวิธีแก้ปัญหาง่ายๆที่ทำให้พฤติกรรมที่ตั้งใจไว้ชัดเจนขึ้น คุณจึงได้รับข้อผิดพลาดและถูกบังคับให้คิดอย่างถูกต้องเกี่ยวกับปัญหาของคุณ เป็นแนวคิด "โยนคุณสู่หลุมแห่งความสำเร็จ" ทั่วไปที่เกิดขึ้นใน C #

C # คุณและถ้าประสบความสำเร็จ

หากคุณต้องการละเว้นข้อยกเว้น (บ่อยกว่าไม่ใช่ความคิดที่ไม่ดี) และดำเนินการวนซ้ำต่อไปให้ใช้บล็อก catch all:

foreach ( var in list )
{
    try{
        //some code
    }catch{
        continue;
    }
}

หากคุณต้องการcontinueเฉพาะเมื่อไม่มีการโยนข้อยกเว้นที่ไม่ถูกจับให้วางไว้continueนอกบล็อกการทดลอง


12
ฉันจะยอมรับสิ่งนี้เป็นคำตอบเนื่องจากคุณเข้าใจสาเหตุที่ Microsoft อาจตัดสินใจไม่ยอมรับการดำเนินการต่อในที่สุด อาจเป็นภาพที่ทำให้ฉันเชื่อเช่นกัน :)
lpaloub

20
คุณสามารถอธิบายแนวคิด "โยนคุณสู่หลุมแห่งความสำเร็จ" ได้หรือไม่? ฉันไม่เข้าใจ :-D
Ant


13
ภาพนี้สร้างโดย Jon Skeet, btw ได้มาจากที่นี่: msmvps.com/blogs/jon_skeet/archive/2010/09/02/…
Fernandes

1
แน่นอนcontinueในfinallyบล็อกจะใช้ได้หากยังคงวนซ้ำเฉพาะที่กำหนดไว้ในfinallyบล็อก อย่างไรก็ตามในคำถามจะพยายามวนรอบ "ด้านนอก" ต่อไป งบที่คล้ายกันที่คุณไม่สามารถมีที่อยู่ภายในfinallyบล็อกreturn, break(เมื่อทำลายออกจากบล็อก) และgoto(เมื่อไปฉลากนอกfinallyบล็อก) สำหรับการอภิปราย Java ที่เกี่ยวข้องดูกลับมาจากบล็อกสุดท้ายในชวา
Jeppe Stig Nielsen

32

นี่คือแหล่งที่เชื่อถือได้:

คำสั่งต่อไม่สามารถออกจากบล็อกในที่สุด (มาตรา 8.10) เมื่อคำสั่งต่อเกิดขึ้นภายในบล็อกสุดท้ายเป้าหมายของคำสั่งต่อจะต้องอยู่ในบล็อกสุดท้ายเดียวกัน มิฉะนั้นจะเกิดข้อผิดพลาดเวลาคอมไพล์

มันจะนำมาจาก MSDN, 8.9.2 ยังคงคำสั่ง

เอกสารระบุว่า:

คำสั่งของบล็อกสุดท้ายจะถูกดำเนินการเสมอเมื่อคอนโทรลออกจากคำสั่ง try นี่เป็นความจริงไม่ว่าการถ่ายโอนการควบคุมจะเกิดขึ้นจากการดำเนินการตามปกติอันเป็นผลมาจากการดำเนินการคำสั่ง break, continue, goto หรือ return หรือเป็นผลมาจากการเผยแพร่ข้อยกเว้นออกจากคำสั่ง try หากเกิดข้อยกเว้นระหว่างดำเนินการบล็อกสุดท้ายข้อยกเว้นจะถูกเผยแพร่ไปยังคำสั่ง try ที่แนบมา หากข้อยกเว้นอื่นอยู่ระหว่างการเผยแพร่ข้อยกเว้นนั้นจะหายไป ขั้นตอนการเผยแพร่ข้อยกเว้นจะกล่าวถึงเพิ่มเติมในคำอธิบายของคำสั่งโยน (ข้อ 8.9.5)

มันมาจากที่นี่8.10 คำสั่งลอง


31

คุณอาจคิดว่ามันสมเหตุสมผล แต่มันไม่สมเหตุสมผลเลย

foreach (var v in List)
{
    try
    {
        //Some code
    }
    catch (Exception)
    {
        //Some more code
        break; or return;
    }
    finally
    {
        continue;
    }
}

คุณตั้งใจจะหยุดพักหรือทำอะไรต่อเมื่อมีข้อยกเว้นเกิดขึ้น? ทีมคอมไพเลอร์ C # ไม่ต้องการตัดสินใจด้วยตัวเองโดยการสมมติbreakหรือcontinue. finally blockแต่พวกเขาตัดสินใจที่จะบ่นสถานการณ์ที่นักพัฒนาจะคลุมเครือต่อการควบคุมการโอนย้ายจาก

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

ฉันหวังว่าคุณจะเข้าใจว่าทำไมสิ่งนี้ถึงไม่รวบรวม!


ในบันทึกที่เกี่ยวข้องแม้ว่าจะไม่มีคำว่า "catch" เส้นทางการดำเนินการตามfinallyคำสั่งจะได้รับผลกระทบจากการcatchออกจากข้อยกเว้นและไม่มีกลไกใดที่จะบอกว่าควรโต้ตอบกับไฟล์continue. ฉันชอบตัวอย่างของคุณเพราะมันแสดงให้เห็นถึงปัญหาที่ใหญ่กว่า
supercat

@supercat เห็นด้วยกับคุณคำตอบของฉันแสดงตัวอย่างสถานการณ์ที่คลุมเครือสำหรับคอมไพเลอร์ยังคงมีปัญหามากมายเกี่ยวกับแนวทางนี้
Sriram Sakthivel

16

ตามที่คนอื่น ๆ ระบุไว้ แต่เน้นไปที่ข้อยกเว้นจริงๆแล้วมันเกี่ยวกับการจัดการการควบคุมการถ่ายโอนที่ไม่ชัดเจน

ในใจของคุณคุณอาจนึกถึงสถานการณ์เช่นนี้:

public static object SafeMethod()
{
    foreach(var item in list)
    {
        try
        {
            try
            {
                //do something that won't transfer control outside
            }
            catch
            {
                //catch everything to not throw exceptions
            }
        }
        finally
        {
            if (someCondition)
                //no exception will be thrown, 
                //so theoretically this could work
                continue;
        }
    }

    return someValue;
}

ในทางทฤษฎีคุณสามารถติดตามขั้นตอนการควบคุมและพูดว่าใช่นี่คือ "ตกลง" ไม่มีการโยนข้อยกเว้นไม่มีการถ่ายโอนการควบคุม แต่นักออกแบบภาษา C # มีปัญหาอื่น ๆ อยู่ในใจ

ข้อยกเว้นที่ถูกโยน

public static void Exception()
{
    try
    {
        foreach(var item in list)
        {
            try
            {
                throw new Exception("What now?");
            }
            finally
            {
                continue;
            }
        }
    }
    catch
    {
        //do I get hit?
    }
}

Goto ที่น่ากลัว

public static void Goto()
{
    foreach(var item in list)
    {
        try
        {
            goto pigsfly;
        }
        finally
        {
            continue;
        }
    }

    pigsfly:
}

การกลับมา

public static object ReturnSomething()
{
    foreach(var item in list)
    {
        try
        {
            return item;
        }
        finally
        {
            continue;
        }
    }
}

เลิก

public static void Break()
{
    foreach(var item in list)
    {
        try
        {
            break;
        }
        finally
        {
            continue;
        }
    }
}

ดังนั้นในการสรุปใช่ในขณะที่มีเป็นเล็กน้อยความเป็นไปได้ของการใช้continueในสถานการณ์ที่ควบคุมไม่ได้ถูกโอน แต่การจัดการที่ดี (ส่วนใหญ่?) ในกรณีที่เกี่ยวข้องกับข้อยกเว้นหรือreturnบล็อก นักออกแบบภาษารู้สึกว่าสิ่งนี้จะคลุมเครือเกินไปและ (น่าจะ) เป็นไปไม่ได้ที่จะมั่นใจได้ว่าในเวลาคอมไพล์ของคุณcontinueจะถูกใช้เฉพาะในกรณีที่ไม่มีการถ่ายโอนโฟลว์การควบคุม


มีสถานการณ์เดียวกันใน java เมื่อ proguard หยุดทำงานในขณะที่สับสน คำอธิบายของคุณค่อนข้างดี C # ให้ข้อผิดพลาดเวลาคอมไพล์ - เหมาะสมอย่างยิ่ง
Dev_Vikram

11

โดยทั่วไปcontinueไม่สมเหตุสมผลเมื่อใช้ในfinallyบล็อก ดูที่นี้:

foreach (var item in list)
{
    try
    {
        throw new Exception();
    }
    finally{
        //doesn't make sense as we are after exception
        continue;
    }
}

"โดยทั่วไป" หลายสิ่งไม่สมเหตุสมผล และไม่ได้หมายความว่ามันไม่ควรทำงาน "โดยเฉพาะ" IE: continueไม่มีเหตุผลนอกคำสั่งลูป แต่ไม่ได้หมายความว่าไม่รองรับ
zerkms

ฉันคิดว่ามันสมเหตุสมผล itemสามารถเป็นไฟล์อ่านล้มเหลว -> finallyปิดไฟล์ continueป้องกันการประมวลผลที่เหลือ
jnovacho

5

"สิ่งนี้จะไม่รวบรวมและฉันคิดว่ามันสมเหตุสมผลแล้ว"

ฉันคิดว่ามันไม่

เมื่อคุณมีจริงcatch(Exception)แล้วคุณไม่ต้องการในที่สุด (และอาจจะไม่ถึงด้วยซ้ำcontinue)

เมื่อคุณมีความเป็นจริงมากขึ้นcatch(SomeException)จะเกิดอะไรขึ้นเมื่อไม่พบข้อยกเว้น? คุณcontinueต้องการไปทางเดียวข้อยกเว้นในการจัดการอีกทางหนึ่ง


2
ฉันคิดว่าคุณจะต้องเมื่อคุณมีfinally catchมักใช้สำหรับการปิดทรัพยากรด้วยวิธีที่เชื่อถือได้
jnovacho

ไม่ใช่แค่ข้อยกเว้นเท่านั้น คุณสามารถมีคำสั่งภายในหรือบล็อกของคุณได้อย่างง่ายดาย ตอนนี้เราทำอะไร? ย้อนกลับหรือวนต่อ? (และถ้าเราไม่ดำเนินการต่อสิ่งที่ถ้ามันเป็นรายการสุดท้ายที่จะย้ำแล้วเราก็ยังคงออกไปข้างนอกหรือไม่และการกลับมาไม่เคยเกิดขึ้น?) แก้ไข: หรือแม้กระทั่งกับป้ายกำกับนอกวงที่สวยมากกระทำที่โอนควบคุมนอกวง . returntrycatchforeachgotoforeach
Chris Sinclair

2
ฉันไม่เห็นด้วยกับ "เมื่อคุณจับได้ (ข้อยกเว้น) อย่างแท้จริงคุณก็ไม่ต้องการในที่สุด จะเกิดอะไรขึ้นหากฉันต้องดำเนินการใด ๆ ที่มีข้อยกเว้นเพิ่มขึ้นหรือไม่
lpaloub

ตกลงในที่สุดก็เหมาะสำหรับreturns เพิ่มเติมในบล็อก แต่โดยปกติการดำเนินการจะดำเนินต่อไปหลังจากที่จับทั้งหมดแล้ว
Henk Holterman

'ในที่สุด' ไม่ใช่ 'จับ' ควรใช้สำหรับรหัสล้างข้อมูล ในที่สุดบล็อกจะทำงานไม่ว่าจะมีข้อยกเว้นหรือไม่ก็ตาม สิ่งต่างๆเช่นการปิดไฟล์หรือการเพิ่มหน่วยความจำ (หากคุณใช้โค้ดที่ไม่มีการจัดการ) เป็นต้นสิ่งเหล่านี้คือสิ่งที่คุณใส่ไว้ในบล็อกสุดท้าย
Robotnik

3

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


3

finallyบล็อกสามารถดำเนินการกับการรอคอยที่จะเป็นข้อยกเว้น rethrown มันไม่สมเหตุสมผลเลยที่จะสามารถออกจากบล็อก (โดย a continueหรืออย่างอื่น) โดยไม่ต้องสร้างข้อยกเว้นขึ้นมาใหม่

หากคุณต้องการวนรอบต่อไปไม่ว่าจะเกิดอะไรขึ้นคุณไม่จำเป็นต้องมีคำสั่งสุดท้าย: เพียงแค่จับข้อยกเว้นและไม่ต้องทำซ้ำ


1

finallyทำงานไม่ว่าจะมีการโยนข้อยกเว้นที่ไม่ถูกจับหรือไม่ก็ตาม คนอื่น ๆ ได้อธิบายแล้วว่าเหตุใดสิ่งนี้จึงcontinueไร้เหตุผล แต่นี่เป็นอีกทางเลือกหนึ่งที่เป็นไปตามเจตนารมณ์ของสิ่งที่รหัสนี้ดูเหมือนจะขอ โดยทั่วไปfinally { continue; }กำลังพูดว่า:

  1. เมื่อมีข้อยกเว้นที่จับได้ให้ดำเนินการต่อ
  2. เมื่อมีข้อยกเว้นที่ไม่ถูกจับได้อนุญาตให้โยนได้ แต่ยังคงดำเนินการต่อไป

(1) สามารถสร้างความพึงพอใจได้โดยวางไว้continueที่ส่วนท้ายของแต่ละcatchอันและ (2) สามารถสร้างความพึงพอใจได้โดยการจัดเก็บข้อยกเว้นที่ไม่ถูกจับเพื่อโยนทิ้งในภายหลัง คุณสามารถเขียนได้ดังนี้:

var exceptions = new List<Exception>();
foreach (var foo in list) {
    try {
        // some code
    } catch (InvalidOperationException ex) {
        // handle specific exception
        continue;
    } catch (Exception ex) {
        exceptions.Add(ex);
        continue;
    }
    // some more code
}
if (exceptions.Any()) {
    throw new AggregateException(exceptions);
}

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


1

ในทางเทคนิคมันเป็นข้อ จำกัด ของ CIL ที่อยู่เบื้องหลัง จากข้อกำหนดภาษา :

ไม่อนุญาตให้ถ่ายโอนการควบคุมเข้าสู่ตัวจัดการการจับหรือในที่สุดข้อยกเว้นผ่านกลไกการจัดการข้อยกเว้น

และ

การถ่ายโอนการควบคุมออกจากภูมิภาคที่มีการป้องกันที่ได้รับอนุญาตเท่านั้นที่ผ่านการเรียนการสอนข้อยกเว้น ( leave, end.filter, end.catchหรือend.finally)

ในหน้าเอกสารสำหรับbrคำแนะนำ :

การควบคุมการถ่ายโอนเข้าและออกจากการลองจับกรองและสุดท้ายไม่สามารถดำเนินการบล็อกได้ด้วยคำสั่งนี้

สุดท้ายนี้ถือเป็นจริงสำหรับทุกคำแนะนำสาขารวมทั้งbeq, brfalseฯลฯ


-1

นักออกแบบภาษาไม่ต้องการ (หรือไม่สามารถ) ให้เหตุผลเกี่ยวกับความหมายของการบล็อกในที่สุดที่ถูกยกเลิกโดยการถ่ายโอนการควบคุม

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

หากเรามีการควบคุมการถ่ายโอนออกจากไฟล์ finallyบล็อกการล้างข้อมูลการถ่ายโอนการควบคุมเดิมจะถูก "ไฮแจ็ก" มันถูกยกเลิกและการควบคุมไปที่อื่น

อรรถศาสตร์สามารถหาได้ ภาษาอื่น ๆ ก็มี

นักออกแบบของ C # ตัดสินใจที่จะไม่อนุญาตให้มีการถ่ายโอนการควบคุมแบบคงที่ "เหมือนโกโต" ดังนั้นจึงทำให้สิ่งต่างๆง่ายขึ้น

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

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


ความแตกต่างคือfinallyตามคำจำกัดความจะต้องดำเนินการตามทันทีโดยดำเนินการถ่ายโอนที่ทริกเกอร์ต่อไป (ข้อยกเว้นที่returnไม่ถูกตรวจจับ ฯลฯ ) มันจะง่ายมากที่จะอนุญาตให้มีการถ่ายโอนแบบ "เหมือน goto" ภายในfinally(ภาษาใดบ้างที่ทำเช่นนี้) แต่การทำเช่นนั้นจะtry { return } finally { ... } ไม่ส่งคืนซึ่งเป็นเรื่องที่คาดไม่ถึงโดยสิ้นเชิง หากfinallyเรียกใช้ฟังก์ชันที่พ่นนั่นไม่ใช่สิ่งเดียวกันจริงๆเพราะเราคาดไว้แล้วว่าอาจมีข้อยกเว้นเกิดขึ้นได้ตลอดเวลาและขัดขวางการไหลปกติ
nmclean

@nmclean: อันที่จริงข้อยกเว้นที่หนีออกมาfinallyนั้นเป็นสิ่งเดียวกันซึ่งอาจส่งผลให้เกิดการไหลของโปรแกรมที่ไม่คาดคิดและไร้เหตุผล ข้อแตกต่างเพียงอย่างเดียวคือนักออกแบบภาษาไม่สามารถปฏิเสธโปรแกรมทั้งหมดที่ในที่สุดการบล็อกอาจทำให้เกิดข้อยกเว้นที่ไม่สามารถจัดการได้แทนที่จะอนุญาตให้โปรแกรมดังกล่าวรวบรวมและหวังว่าโปรแกรมจะยอมรับผลใด ๆ ที่อาจตามมาจากการละทิ้งข้อยกเว้นก่อนหน้านี้ ลำดับ.
supercat

@supercat ผมยอมรับว่าจะแบ่งการไหลคาดว่า แต่จุดของฉันคือว่าที่เป็นเสมอกรณีสำหรับการจัดการข้อยกเว้นไม่ว่าจะเป็นการไหลของกระแสเป็นfinallyหรือไม่ ตามตรรกะของย่อหน้าสุดท้ายของ Kaz ฟังก์ชั่นควรมีอิสระที่จะส่งผลต่อการไหลในขอบเขตของผู้โทรด้วยวิธีการcontinueอื่น ๆ เนื่องจากได้รับอนุญาตให้ทำเช่นนั้นได้โดยมีข้อยกเว้น แต่สิ่งนี้ไม่ได้รับอนุญาต ข้อยกเว้นเป็นข้อยกเว้นเพียงอย่างเดียวของกฎนี้ดังนั้นจึงมีชื่อว่า "ข้อยกเว้น" (หรือ "ขัดจังหวะ")
nmclean

@nmclean: ข้อยกเว้นที่ไม่ซ้อนกันแสดงถึงโฟลว์การควบคุมซึ่งแตกต่างจากการดำเนินการปกติ แต่ยังคงมีโครงสร้าง คำสั่งต่อจากบล็อกควรดำเนินการก็ต่อเมื่อมีการตรวจพบข้อยกเว้นทั้งหมดที่เกิดขึ้นภายในบล็อกนั้น นั่นอาจดูเหมือนเป็นความคาดหวังที่สมเหตุสมผล แต่ข้อยกเว้นที่เกิดขึ้นภายในfinallyบล็อกสามารถละเมิดได้ เป็นสถานการณ์ที่น่ารังเกียจจริงๆซึ่ง IMHO ควรได้รับการแก้ไขโดยอย่างน้อยที่สุดให้finallyบล็อกทราบเกี่ยวกับข้อยกเว้นที่รอดำเนินการเพื่อให้สามารถสร้างวัตถุข้อยกเว้นแบบผสมได้
supercat

@mmclean ขออภัยฉันไม่ยอมรับว่าชื่อ "ข้อยกเว้น" มาจาก "ข้อยกเว้นของกฎ" (เกี่ยวกับการควบคุม) ที่เฉพาะเจาะจงสำหรับ C # LOL โฟลว์การควบคุมที่เปลี่ยนแปลงลักษณะของข้อยกเว้นเป็นเพียงการถ่ายโอนการควบคุมไดนามิกที่ไม่ใช่โลคัล การถ่ายโอนการควบคุมปกติภายในขอบเขตคำศัพท์เดียวกัน (ไม่มีการคลี่คลายเกิดขึ้น) ถือได้ว่าเป็นกรณีพิเศษ
Kaz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.