ทำไมจึงลอง {... } ในที่สุด {…} ดี ลอง {…} จับ {} ไม่ดีใช่ไหม


201

ฉันเคยเห็นคนพูดว่ามันเป็นรูปแบบที่ไม่ดีที่จะใช้ catch โดยไม่มีข้อโต้แย้งโดยเฉพาะถ้า catch นั้นไม่ได้ทำอะไร:

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
catch   // No args, so it will catch any exception
{}
reader.Close();

อย่างไรก็ตามนี่ถือว่าเป็นรูปแบบที่ดี:

StreamReader reader=new  StreamReader("myfile.txt");
try
{
  int i = 5 / 0;
}
finally   // Will execute despite any exception
{
  reader.Close();
}

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

มิฉะนั้นจะมีอะไรพิเศษเกี่ยวกับในที่สุด?


7
ก่อนที่คุณจะพยายามจับเสือที่คุณไม่สามารถจัดการได้คุณควรบันทึกความปรารถนาสุดท้ายของคุณ

หัวข้อข้อยกเว้นในเอกสารอาจให้ข้อมูลเชิงลึกที่ดี ดูตัวอย่างสุดท้ายของบล็อกด้วย
Athafoud

คำตอบ:


357

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


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

3
ในกรณีส่วนใหญ่จะเห็นได้ชัดว่าทำไมข้อยกเว้นเฉพาะจะเกิดขึ้นจากระดับแอปพลิเคชัน (เช่นการตั้งค่าการกำหนดค่าบางอย่าง) กว่าในระดับ librray ระดับ
Mark Cidade

88
เดวิด - ฉันต้องการให้โปรแกรมทำงานล้มเหลวอย่างรวดเร็วดังนั้นฉันจึงสามารถรับรู้ปัญหาแทนที่จะปล่อยให้โปรแกรมทำงานในสถานะที่ไม่รู้จัก
Erik Forbes

6
หากโปรแกรมของคุณอยู่ในสถานะที่ไม่รู้จักหลังจากเกิดข้อยกเว้นแสดงว่าคุณทำผิดรหัส
Zan Lynx

41
@DavidArno รหัสใด ๆ ที่เขียนด้วย encapsulation ในใจควรจัดการข้อยกเว้นภายในขอบเขตของพวกเขา ควรมีการส่งผ่านสิ่งอื่นใดเพื่อให้คนอื่นจัดการ หากฉันมีแอปพลิเคชันที่ได้รับชื่อไฟล์จากผู้ใช้ให้อ่านไฟล์และผู้อ่านไฟล์ของฉันได้รับข้อยกเว้นในการเปิดไฟล์มันควรส่งต่อไฟล์นั้น (หรือใช้ข้อยกเว้นและโยนใหม่) เพื่อให้แอปพลิเคชันสามารถพูดได้ , เฮ้ - ไฟล์ไม่เปิด, ลองถามผู้ใช้คนอื่นดู ตัวอ่านไฟล์ไม่ควรแจ้งผู้ใช้หรือดำเนินการอื่นใดตามการตอบสนอง วัตถุประสงค์เพียงอย่างเดียวคือการอ่านไฟล์
iheanyi

62

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

"Catch" เป็นคำสั่ง "ฉันสามารถกู้คืนจากข้อยกเว้นนี้" คุณควรกู้คืนจากข้อยกเว้นที่คุณสามารถแก้ไขได้จริงๆ - การจับโดยไม่มีข้อโต้แย้งกล่าวว่า "เฮ้ฉันสามารถกู้คืนจากอะไรก็ได้!" ซึ่งเกือบจะไม่จริง

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


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

32

เพราะเมื่อหนึ่งบรรทัดนั้นเกิดข้อยกเว้นคุณจะไม่รู้ตัว

ด้วยบล็อกแรกของรหัสข้อยกเว้นจะถูกดูดซับเพียงโปรแกรมจะยังคงทำงานแม้ว่าสถานะของโปรแกรมอาจจะผิด

กับบล็อกที่สองยกเว้นจะถูกโยนและฟองอากาศขึ้นแต่reader.Close()ยังคงรับประกันว่าจะทำงาน

หากไม่คาดว่าจะมีข้อยกเว้นอย่าลอง try..catch block ดังนั้นจะเป็นการดีบั๊กในภายหลังเมื่อโปรแกรมเข้าสู่สถานะไม่ดีและคุณไม่มีความคิดว่าทำไม


21

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

นอกจากนี้ยังเป็นการดีกว่าที่จะลองใช้โครงสร้างต่อไปนี้:

using (StreamReader reader=new  StreamReader("myfile.txt"))
{
}

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


5
สิ่งนี้ไม่ถูกต้อง การใช้ไม่ห่อโค้ดด้วยการลอง / จับมันควรจะบอกว่าลอง / ในที่สุด
pr0nin

8

ในขณะที่บล็อคโค้ด 2 รายการต่อไปนี้จะเท่ากัน แต่จะไม่เท่ากัน

try
{
  int i = 1/0; 
}
catch
{
  reader.Close();
  throw;
}

try
{
  int i = 1/0;
}
finally
{
  reader.Close();
}
  1. 'ที่สุด' เป็นรหัสเปิดเผยความตั้งใจ คุณประกาศให้คอมไพเลอร์และโปรแกรมเมอร์คนอื่น ๆ ทราบว่าโค้ดนี้จำเป็นต้องรันไม่ว่าจะเกิดอะไรขึ้นก็ตาม
  2. หากคุณมี catch catch หลายบล็อกและคุณมี code cleanup คุณก็ต้องใช้ในที่สุด หากไม่มีสุดท้ายคุณจะทำซ้ำรหัสการล้างข้อมูลของคุณในแต่ละ catch block (หลักการแบบแห้ง)

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


5

ฉันเห็นด้วยกับสิ่งที่ดูเหมือนจะเป็นฉันทามติที่นี่ - 'จับ' ว่างเปล่าไม่ดีเพราะมันปกปิดสิ่งยกเว้นที่อาจเกิดขึ้นในบล็อกลอง

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

using (StreamReader reader = new StreamReader('myfile.txt'))
{
    // do stuff here
} // reader.dispose() is called automatically

คุณสามารถใช้คำสั่ง 'ใช้' กับวัตถุใด ๆ ที่ใช้ IDisposable วิธีการกำจัดวัตถุ () ได้รับการเรียกโดยอัตโนมัติในตอนท้ายของบล็อก


4

ใช้Try..Catch..Finallyหากวิธีการของคุณรู้วิธีจัดการข้อยกเว้นในเครื่อง ข้อยกเว้นเกิดขึ้นในการลองจัดการในการดักจับและหลังจากการล้างข้อมูลเสร็จสิ้นในที่สุด

ในกรณีที่วิธีการของคุณไม่ทราบวิธีการจัดการข้อยกเว้น แต่ต้องล้างข้อมูลเมื่อมีการใช้งาน Try..Finally

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

โดยTry..Finallyจะทำให้มั่นใจได้ว่าการล้างข้อมูลในเครื่องเสร็จสิ้นก่อนเผยแพร่ข้อยกเว้นไปยังวิธีการโทร


1
โดยพื้นฐานแล้วคำตอบนี้คือคำตอบที่ดีที่สุด มันเป็นเรื่องดีถ้าอยู่ในนิสัยลอง / จับ / ในที่สุดแม้ว่าหนึ่งในสองหลังนั้นจะว่างเปล่า มีสถานการณ์ที่หายากมากซึ่งบล็อก catch อาจมีอยู่และว่างเปล่า แต่อย่างน้อยถ้าคุณเขียนลอง / catch / ในที่สุดคุณจะเห็นบล็อคว่างเปล่าในขณะที่คุณกำลังอ่านรหัส การมีบล็อกว่างเปล่าในที่สุดก็มีประโยชน์เช่นเดียวกัน หากคุณต้องการล้างข้อมูลในภายหลังหรือจำเป็นต้องตรวจแก้จุดบกพร่องในขณะที่มีข้อยกเว้นมันมีประโยชน์อย่างเหลือเชื่อ
Jesse Williams

3

การลอง .. ในที่สุดการบล็อกจะยังคงส่งข้อยกเว้นใด ๆ ทั้งหมดfinallyจะตรวจสอบให้แน่ใจว่ามีการเรียกใช้รหัสการล้างข้อมูลก่อนที่จะเกิดข้อยกเว้น

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

อีกเหตุผลหนึ่งก็คือการลองทำ .. จับแบบนี้ไม่ถูกต้องสมบูรณ์ สิ่งที่คุณพูดโดยทำสิ่งนี้คือ "ไม่ว่าจะเกิดอะไรขึ้นฉันสามารถจัดการกับมันได้" สิ่งที่เกี่ยวกับStackOverflowExceptionคุณสามารถทำความสะอาดหลังจากที่? เกี่ยวกับOutOfMemoryExceptionอะไร โดยทั่วไปคุณควรจัดการข้อยกเว้นที่คุณคาดหวังและรู้วิธีจัดการเท่านั้น


2

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

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


2

จากมุมมองที่สามารถอ่านได้จะบอกผู้อ่านโค้ดในอนาคตได้ชัดเจนยิ่งขึ้น "สิ่งนี้ที่นี่มีความสำคัญมันต้องทำไม่ว่าจะเกิดอะไรขึ้น" ดีจัง.

นอกจากนี้คำสั่งจับที่ว่างเปล่ามักจะมี "กลิ่น" บางอย่างกับพวกเขา พวกเขาอาจเป็นสัญญาณว่านักพัฒนาไม่ได้คิดถึงข้อยกเว้นต่าง ๆ ที่อาจเกิดขึ้นและวิธีจัดการกับพวกเขา


2

ในที่สุดก็เป็นตัวเลือก - ไม่มีเหตุผลที่จะมีการบล็อก "ในที่สุด" ถ้าไม่มีทรัพยากรที่จะล้าง


2

นำมาจาก: ที่นี่

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

Dim str As Stream = GetStream () If (str.CanRead) จากนั้นโค้ด 'เพื่ออ่าน stream สิ้นสุดถ้า

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

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


2
สกอตต์ - หากข้อความที่คุณยกมาข้างต้นอยู่เบื้องหลัง paywall ของ expertexchange.com คุณอาจไม่ควรโพสต์ข้อความที่นี่ ฉันอาจจะผิดในเรื่องนี้ แต่ฉันจะเดิมพันที่ไม่ใช่ความคิดที่ดี
Onorio Catenacci

2

เป็นการปฏิบัติที่ไม่ถูกต้องในการเพิ่ม catch clause เพียงเพื่อสร้างข้อยกเว้นใหม่


2

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

CLR ไม่ได้กำจัดการรั่วไหลอย่างสมบูรณ์ ... การรั่วไหลของหน่วยความจำสามารถเกิดขึ้นได้หากโปรแกรมทำการเก็บข้อมูลอ้างอิงไปยังวัตถุที่ไม่ต้องการโดยไม่ตั้งใจ

ตัวอย่างเช่นเมื่อคุณเปิดการเชื่อมต่อไฟล์หรือฐานข้อมูลเครื่องของคุณจะจัดสรรหน่วยความจำเพื่อรองรับธุรกรรมนั้นและหน่วยความจำนั้นจะไม่ถูกเก็บไว้เว้นแต่ว่าคำสั่งการกำจัดหรือปิดถูกดำเนินการ แต่ถ้าในระหว่างการทำธุรกรรมมีข้อผิดพลาดเกิดขึ้นคำสั่งดำเนินการจะถูกยกเลิกไม่เว้นแต่จะอยู่ในtry.. finally..บล็อก

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

และคุณควรอนุญาตให้ทั้งสองทำงานร่วมกันเพื่อประโยชน์

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

try
{
  StreamReader reader=new  StreamReader("myfile.txt");
  //do other stuff
}
catch(Exception ex){
 // Create log, or show notification
 generic.Createlog("Error", ex.message);
}
finally   // Will execute despite any exception
{
  reader.Close();
}

1

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


1

สำหรับคนหนึ่งมันเป็นการปฏิบัติที่ไม่ดีที่จะจับข้อยกเว้นที่คุณไม่ต้องการจัดการ ตรวจสอบบทที่ 5 เกี่ยวกับผลการดำเนินงานสุทธิจากการปรับปรุง .NET การประยุกต์ใช้ผลการปฏิบัติงานและการปรับขยาย โปรดทราบว่าคุณควรโหลดสตรีมในบล็อกลองซึ่งอาจทำให้คุณสามารถตรวจสอบข้อยกเว้นที่เกี่ยวข้องได้หากล้มเหลว การสร้างสตรีมนอกบล็อกลองใช้เพื่อกำจัดจุดประสงค์


0

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


0

ปัญหาของบล็อค try / catch ที่ตรวจจับข้อยกเว้นทั้งหมดคือตอนนี้โปรแกรมของคุณอยู่ในสถานะไม่แน่นอนหากมีข้อยกเว้นที่ไม่รู้จักเกิดขึ้น สิ่งนี้ขัดต่อกฎการล้มเหลวอย่างสมบูรณ์ - คุณไม่ต้องการให้โปรแกรมดำเนินการต่อหากมีข้อยกเว้นเกิดขึ้น ลอง / จับด้านบนจะจับ OutOfMemoryExceptions แต่นั่นเป็นสถานะที่โปรแกรมของคุณจะไม่ทำงาน

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


0

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

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

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

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

อนึ่ง Stream และ StreamReader ทั้งคู่ใช้ IDisposable และสามารถห่อในบล็อก 'using' 'การใช้' บล็อกนั้นมีความหมายเทียบเท่ากับการลอง / สุดท้าย (ไม่ 'จับ') ดังนั้นตัวอย่างของคุณอาจแสดงได้มากกว่า:

using (StreamReader reader = new  StreamReader("myfile.txt"))
{
  int i = 5 / 0;
}

... ซึ่งจะปิดและกำจัดอินสแตนซ์ StreamReader เมื่อไม่อยู่ในขอบเขต หวังว่านี่จะช่วยได้


0

ลอง {…} catch {} ไม่เลวเสมอไป มันไม่ใช่รูปแบบทั่วไป แต่ฉันมักจะใช้เมื่อฉันต้องการปิดทรัพยากรไม่ว่าจะเป็นอะไรเช่นปิดซ็อกเก็ตเปิด (อาจ) ที่ส่วนท้ายของเธรด

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