Питання: Чому Java / C # не може реалізувати RAII?
Пояснення: Я знаю, що сміттєзбірник не є детермінованим. Таким чином, з поточними особливостями мови неможливо автоматично викликати метод об'єкта Dispose () при виході з області дії. Але чи можна додати таку детерміновану ознаку?
Моє розуміння:
Я вважаю, що реалізація RAII повинна відповідати двом вимогам:
1. Термін експлуатації ресурсу повинен бути пов'язаний із сферою застосування.
2. Неявне. Вивільнення ресурсу повинно відбуватися без явного твердження програміста. Аналогічно сміттєзбірнику, що звільняє пам'ять без явного твердження. "Неявність" має виникати лише в точці використання класу. Звичайно, автор бібліотеки класів повинен явно реалізувати деструктор або метод Dispose ().
Java / C # задовольняють пункт 1. У C # ресурс, що реалізує IDisposable, може бути прив’язаний до області "використання":
void test()
{
using(Resource r = new Resource())
{
r.foo();
}//resource released on scope exit
}
Це не задовольняє пункт 2. Програміст повинен явно прив'язати об'єкт до спеціальної області "використання". Програмісти можуть (і робити) забути явно прив’язати ресурс до сфери, створюючи витік.
Насправді блоки "використання" перетворюються компілятором для спроби остаточного розпорядження () кодом. Він має такий самий чіткий характер, як шаблон спроби остаточного розпорядження (). Без неявного випуску гачком сфери є синтаксичний цукор.
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 #, щоб дозволити спеціальні об'єкти, які підключені до стека за допомогою смарт-покажчика. Ця функція дозволить вам позначити клас як обмежений діапазон, щоб він завжди створювався гаком до стеку. Можуть бути варіанти для різних типів смарт-покажчиків.
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
з ніколи не запускаються, незалежно від того, як вони спрацьовують. Додавання неявного знищення в кінці області не допоможе цьому.