Почему в .NET нет RAII?
Будучи в первую очередь разработчиком C ++, отсутствиеRAII (приобретение ресурсов является инициализацией) в Java и .NET меня всегда беспокоило. Тот факт, что ответственность за очистку переходит от автора класса к его потребителю (посредствомtry finally
или .NETusing
сооружатьКажется, заметно уступает.
Я понимаю, почему в Java нет поддержки RAII, поскольку все объекты расположены в куче, а сборщик мусора по своей сути не поддерживает детерминированное уничтожение, но в .NET с введением типов-значений (struct
У нас есть (на первый взгляд) идеальный кандидат в RAII. Тип значения, созданный в стеке, имеет четко определенную область видимости, и можно использовать семантику деструктора C ++. Однако 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();
}
}
Я не могу не закончить цитатой по поводу, которую я когда-то видел, но в настоящее время не могу найти ее происхождение.
Вы можете взять мое детерминированное уничтожение, когда моя холодная мертвая рука выходит за рамки. -скоро