主に C++ の開発者である私は、Java と .NET にRAII (Resource Acquisition Is Initialization)がないことにいつも悩まされてきました。クリーンアップの責任がクラスの作成者から消費者に移されたという事実 (try finally
または .NET のusing
コンストラクトによって) は、著しく劣っているように思われます。
すべてのオブジェクトがヒープ上にあり、ガベージ コレクターが本質的に決定論的破壊をサポートしていないため、Java で RAII がサポートされていない理由がわかりましたが、値型 ( struct
) の導入により .NET では (一見) RAIIの完璧な候補。スタック上に作成された値型には明確に定義されたスコープがあり、C++ デストラクター セマンティクスを使用できます。ただし、CLR では、値型がデストラクタを持つことは許可されていません。
私のランダムな検索では、値の型がボックス化されている場合、ガベージ コレクターの管轄下にあるため、その破棄が非決定的になるという 1 つの引数が見つかりました。この議論は十分に強力ではないと感じています。RAII の利点は、デストラクタを持つ値型をボックス化 (またはクラス メンバーとして使用) できないと言うのに十分大きいです。
簡単に言うと、私の質問は次のとおりです。RAII を .NET に導入するために値型を使用できない理由は他にありますか? (または、RAII の明らかな利点についての私の議論には誤りがあると思いますか?)
編集:最初の4つの回答が要点を逃したため、質問を明確に表現していなかったに違いありません。私はその非決定論的特性について知っており、構造について知っており、これら2つのオプションは RAII よりも劣っていると感じています。は、クラスの消費者が覚えておかなければならないもう 1 つのことです (ブロックに aを入れるのを忘れた人は何人いますか?)。私の質問は、言語設計に関する哲学的なものです。なぜそうなのか、改善できるのでしょうか?Finalize
using
using
StreamReader
using
たとえば、一般的な決定論的に破壊可能な値型を使用すると、using
andlock
キーワードを冗長にすることができます (ライブラリ クラスによって達成可能)。
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();
}
}
私は、かつて見たが、現在その出所を見つけることができない適切な引用で終わらせざるを得ません。
私の冷たい死んだ手が範囲外になると、私の決定論的破壊を受け取ることができます. --アノン