Будучи в первую очередь разработчиком С++, отсутствие RAII (Инициализация приобретения ресурсов) в Java и .NET всегда беспокоило меня. Тот факт, что бремя уборки переносится от автора класса к его потребителю (с помощью try finally
или .NET using
construct), кажется, заметно уступает.
Я вижу, почему в Java нет поддержки для RAII, поскольку все объекты находятся в куче, а сборщик мусора по сути не поддерживает детерминированное уничтожение, а в .NET с введением типов значений (struct
) у нас есть (по-видимому) идеальный кандидат для RAII. Тип значения, созданный в стеке, имеет четко определенную область и можно использовать семантику деструктора С++. Однако CLR не допускает, чтобы тип значения имел деструктор.
Мои случайные поиски обнаружили один аргумент, что если тип значения в штучной упаковке, он подпадает под юрисдикцию сборщика мусора, и поэтому его уничтожение становится недетерминирована. Я считаю, что этот аргумент недостаточно силен, преимущества RAII достаточно велики, чтобы сказать, что тип значения с деструктором не может быть помещен в коробку (или использоваться как член класса).
Чтобы сократить длинный рассказ, мой вопрос: существуют ли какие-либо другие типы значений причин, которые нельзя использовать для внедрения RAII в .NET? (или вы считаете, что мой аргумент о очевидных преимуществах RAII ошибочен?)
Изменить: Я, должно быть, не сформулировал вопрос четко, так как первые четыре ответа пропустили точку. Я знаю о Finalize
и его недетерминированных характеристиках, я знаю о конструкции using
, и я чувствую, что эти два варианта уступают RAII. using
- еще одна вещь, которую должен помнить потребитель класса (сколько людей забыли поставить StreamReader
в блок using
?). Мой вопрос - философский вопрос о дизайне языка, почему он так и может быть улучшен?
Например, с помощью генерического детерминистически разрушаемого типа значений я могу сделать ключевые слова using
и lock
избыточными (достижимыми классами библиотек):
public struct Disposer<T> where T : IDisposable
{
T val;
public Disposer(T t) { val = t; }
public T Value { get { return val; } }
~Disposer() // Currently illegal
{
if (val != default(T))
val.Dispose();
}
}
Я не могу не кончить цитатой, которую я когда-то видел, но не могу найти ее происхождения.
Вы можете принять мое детерминированное разрушение, когда моя холодная мертвая рука выходит из сферы действия. --Anon