【发布时间】:2010-09-15 11:28:45
【问题描述】:
作为主要的 C++ 开发人员,Java 和 .NET 中没有 RAII (Resource Acquisition Is Initialization) 一直困扰着我。清理的责任从类编写者转移到其消费者(通过try finally 或.NET 的using construct)这一事实似乎明显逊色。
我明白为什么在 Java 中不支持 RAII,因为所有对象都位于堆上,而垃圾收集器本身不支持确定性销毁,但在 .NET 中引入了值类型 (struct)我们有(看似)完美的 RAII 候选人。在堆栈上创建的值类型具有明确定义的范围,并且可以使用 C++ 析构函数语义。但是 CLR 不允许值类型具有析构函数。
我的随机搜索发现了一个论点,即如果值类型是boxed,它属于垃圾收集器的管辖范围,因此它的销毁变得不确定。 我觉得这个论点不够有力,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();
}
}
我不禁以我曾经看过但目前无法找到其来源的恰如其分的报价作为结尾。
当我冰冷的死手超出范围时,您可以承担我的确定性破坏。 --匿名
【问题讨论】:
标签: .net struct destructor raii value-type