คำถาม: ทำไม Java / C # ไม่สามารถใช้ RAII ได้
ชี้แจง: ฉันรู้ว่าตัวรวบรวมขยะไม่ได้กำหนดไว้ ดังนั้นด้วยคุณสมบัติภาษาปัจจุบันจึงเป็นไปไม่ได้ที่วิธีการกำจัด () ของวัตถุจะถูกเรียกโดยอัตโนมัติเมื่อออกจากขอบเขต แต่สามารถเพิ่มคุณสมบัติพิเศษดังกล่าวได้หรือไม่
ความเข้าใจของฉัน:
ฉันรู้สึกว่าการนำไปปฏิบัติของ RAII ต้องเป็นไปตามข้อกำหนดสองประการ:
1. อายุการใช้งานของทรัพยากรจะต้องอยู่ในขอบเขต
2. โดยปริยาย การเพิ่มทรัพยากรต้องเกิดขึ้นโดยไม่มีคำสั่งอย่างชัดเจนจากโปรแกรมเมอร์ คล้ายกับตัวรวบรวมขยะที่เพิ่มหน่วยความจำโดยไม่ต้องมีคำสั่งที่ชัดเจน "implicitness" จะต้องเกิดขึ้นเมื่อใช้งานในชั้นเรียนเท่านั้น แน่นอนว่าผู้สร้างไลบรารีคลาสต้องใช้เมธอด destructor หรือ Dispose () อย่างชัดเจน
Java / C # พอใจจุดที่ 1 ใน C # ทรัพยากรการใช้ IDisposable สามารถถูกผูกไว้กับขอบเขต "using":
void test()
{
using(Resource r = new Resource())
{
r.foo();
}//resource released on scope exit
}
สิ่งนี้ไม่เป็นไปตามจุดที่ 2 โปรแกรมเมอร์ต้องผูกวัตถุกับขอบเขต "ใช้" อย่างชัดเจน โปรแกรมเมอร์สามารถ (และทำ) ลืมผูกอย่างชัดเจนทรัพยากรกับขอบเขตสร้างการรั่วไหล
ในความเป็นจริงแล้วคอมไพเลอร์จะทำการแปลงบล็อค "ใช้" เป็นโค้ด try-final-dispose () มีลักษณะที่ชัดเจนเหมือนกันของรูปแบบ try-final-dispose () หากไม่มีการปล่อยโดยนัยเบ็ดไปยังขอบเขตคือน้ำตาลประโยค
void test()
{
//Programmer forgot (or was not aware of the need) to explicitly
//bind Resource to a scope.
Resource r = new Resource();
r.foo();
}//resource leaked!!!
ฉันคิดว่ามันคุ้มค่าที่จะสร้างฟีเจอร์ภาษาใน Java / C # ที่อนุญาตให้วัตถุพิเศษที่เชื่อมต่อกับสแต็กผ่านตัวชี้อัจฉริยะ คุณลักษณะนี้จะช่วยให้คุณสามารถตั้งค่าสถานะคลาสเป็นขอบเขตขอบเขตเพื่อให้ถูกสร้างด้วย hook ไปยังสแต็กเสมอ อาจมีตัวเลือกสำหรับพอยน์เตอร์พอยน์เตอร์ที่แตกต่างกัน
class Resource - ScopeBound
{
/* class details */
void Dispose()
{
//free resource
}
}
void test()
{
//class Resource was flagged as ScopeBound so the tie to the stack is implicit.
Resource r = new Resource(); //r is a smart-pointer
r.foo();
}//resource released on scope exit.
ฉันคิดว่าโดยนัยคือ "คุ้มค่า" เช่นเดียวกับการเก็บขยะโดยนัยก็คือ "คุ้มค่า" การใช้บล็อกอย่างชัดเจนนั้นทำให้ดวงตาสดชื่น แต่ไม่มีข้อได้เปรียบทางความหมายมากกว่าการพยายามกำจัด ()
มันใช้งานไม่ได้กับคุณลักษณะดังกล่าวในภาษา Java / C # หรือไม่? มันจะถูกนำมาใช้โดยไม่ทำลายรหัสเก่าหรือไม่
using
การดำเนินการของDispose
มีการประกัน (ดีลดราคากระบวนการที่กำลังจะตายโดยไม่มีข้อยกเว้นถูกโยนที่จุดที่การล้างข้อมูลทั้งหมดน่าจะกลายเป็นที่สงสัย)
struct
) แต่พวกเขาจะหลีกเลี่ยงโดยปกติยกเว้นในกรณีที่พิเศษมาก ดูเพิ่มเติม
Dispose
s จะเคยทำงานโดยไม่คำนึงถึงวิธีการที่พวกเขากำลังเรียก การเพิ่มการทำลายโดยนัยเมื่อสิ้นสุดขอบเขตจะไม่ช่วย