Soru: Java / C # neden RAII uygulayamıyor?
Açıklama: Çöp toplayıcının deterministik olmadığını biliyorum. Dolayısıyla, geçerli dil özellikleri ile bir nesnenin Dispose () yönteminin kapsam çıkışında otomatik olarak çağrılması mümkün değildir. Ancak böyle belirleyici bir özellik eklenebilir mi?
Benim anlayış:
RAII uygulamasının iki gereksinimi karşılaması gerektiğini düşünüyorum:
1. Bir kaynağın ömrü bir kapsama bağlı olmalıdır.
2. Örtük. Kaynağın serbest bırakılması, programcının açık bir ifadesi olmadan gerçekleşmelidir. Açık bir ifade olmadan hafızayı boşaltan bir çöp toplayıcısına benzer. “Açıklık” sadece sınıfın kullanım noktasında meydana gelir. Sınıf kütüphanesi yaratıcısı elbette açıkça bir destructor veya Dispose () yöntemini uygulamalıdır.
Java / C #, 1. noktayı karşılar. C # 'da, IDisposable'ı uygulayan bir kaynak, "kullanma" kapsamına bağlanabilir:
void test()
{
using(Resource r = new Resource())
{
r.foo();
}//resource released on scope exit
}
Bu, 2. noktayı karşılamaz. Programcı, nesneyi özel bir "kullanma" kapsamına açıkça bağlamalıdır. Programcılar, bir sızıntı yaratarak kaynağı açıkça bir kapsam ile ilişkilendirmeyi unuturlar (ve yaparlar).
Aslında "using" blokları, derleyici tarafından try-finally-dispose () koduna dönüştürülür. Try-finally-dispose () modelinin aynı özelliğine sahiptir. Örtük bir salıverme olmadan, kapsamın kancası sözdizimsel şekerdir.
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 # dilinde, bir akıllı işaretçi ile yığına bağlı özel nesnelere izin veren bir dil özelliği oluşturmaya değeceğini düşünüyorum. Bu özellik, bir sınıfı kapsama bağlı olarak işaretlemenize izin verir, böylece her zaman yığına bir kanca ile oluşturulur. Farklı akıllı işaretçiler için seçenekler olabilir.
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.
Bence dolaysızlığın "buna değer" olduğunu düşünüyorum. Çöp toplama işleminin ima ettiği gibi "buna değer". Açık kullanım blokları gözler üzerinde canlandırıcıdır, ancak try-finally-dispose () yöntemine göre anlamsal bir avantaj sağlamaz.
Böyle bir özelliğin Java / C # dillerine uygulanması pratik değil mi? Eski kodu bozmadan tanıtılabilir mi?
using
yerine getirilmesinin garanti Dispose
edildiğine dikkat edin (peki, bir istisna atılmadan aniden ölmekte olan sürecin iskonto edilmesi, ki bu noktada tüm temizlik muhtemelen dağılmakta).
struct
), ama bunlar genellikle çok özel durumlar dışında kaçınılır. Ayrıca bakınız .
Dispose
s olan hiç bakılmaksızın tetikleyen nasıl yapıldığından, çalıştırın. Kapsamın sonunda örtülü bir yıkım eklemek buna yardımcı olmaz.