Pertanyaan: Mengapa Java / C # tidak bisa mengimplementasikan RAII?
Klarifikasi: Saya tahu pengumpul sampah tidak deterministik. Jadi dengan fitur bahasa saat ini, metode Buang () objek tidak mungkin dipanggil secara otomatis pada scope exit. Tetapi dapatkah fitur deterministik seperti itu ditambahkan?
Pemahaman saya:
Saya merasa implementasi RAII harus memenuhi dua persyaratan:
1. Masa pakai sumber daya harus terikat pada ruang lingkup.
2. Tersirat. Pembebasan sumber daya harus terjadi tanpa pernyataan eksplisit oleh programmer. Dianalogikan dengan pengumpul sampah yang membebaskan memori tanpa pernyataan eksplisit. "Implisit" hanya perlu terjadi pada saat penggunaan kelas. Pembuat perpustakaan kelas tentu saja harus secara eksplisit menerapkan metode destruktor atau Buang ().
Java / C # memuaskan poin 1. Dalam C # sumber daya mengimplementasikan IDisposable dapat terikat ke lingkup "menggunakan":
void test()
{
using(Resource r = new Resource())
{
r.foo();
}//resource released on scope exit
}
Ini tidak memenuhi poin 2. Programmer harus secara eksplisit mengikat objek ke lingkup "menggunakan" khusus. Pemrogram dapat (dan memang) lupa untuk secara eksplisit mengikat sumber daya ke ruang lingkup, menciptakan kebocoran.
Faktanya, blok "using" dikonversi menjadi kode try-akhirnya-buang () oleh kompiler. Ini memiliki sifat eksplisit yang sama dari pola coba-akhirnya-buang (). Tanpa pelepasan implisit, kait ke lingkup adalah gula sintaksis.
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!!!
Saya pikir layak membuat fitur bahasa di Java / C # yang memungkinkan objek khusus yang terhubung ke stack melalui smart-pointer. Fitur ini akan memungkinkan Anda untuk menandai kelas sebagai lingkup-terikat, sehingga selalu dibuat dengan kait ke tumpukan. Mungkin ada opsi untuk berbagai jenis pointer cerdas.
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.
Saya pikir implisit adalah "sepadan". Sama seperti implikasi dari pengumpulan sampah adalah "sepadan". Eksplisit menggunakan blok menyegarkan di mata, tetapi tidak menawarkan keuntungan semantik dari coba-akhirnya buang ()
Apakah tidak praktis untuk mengimplementasikan fitur seperti itu ke dalam bahasa Java / C #? Bisakah itu diperkenalkan tanpa melanggar kode lama?
using
pelaksanaan Dispose
yang dijamin (baik, mendiskontokan proses tiba-tiba mati tanpa pengecualian yang dilemparkan, di mana titik semua pembersihan mungkin menjadi diperdebatkan).
struct
), tetapi mereka biasanya dihindari kecuali dalam kasus yang sangat khusus. Lihat juga .
Dispose
s pernah dijalankan, terlepas dari bagaimana mereka dipicu. Menambahkan penghancuran implisit di akhir ruang lingkup tidak akan membantu itu.