为什么C#中的Dispose模式在C++中不像RAII那样工作

Bla*_*ICE 8 .net c# c++ raii

所以我只是阅读非垃圾收集语言的RAII模式,这部分引起了我的注意:

开发自定义类时通常会遇到此限制.C#和Java中的自定义类必须显式实现dispose方法,以便与客户端代码进行处置兼容.dispose方法必须包含显式关闭属于该类的所有子资源.在使用RAII的C++中不存在这种限制,其中自定义类的析构函数自动地递归地破坏所有子资源而不需要任何显式代码.

为什么C++可以正确地跟踪在RAII模式中分配的这些资源,但是我们没有使用C#using构造获得这个可爱的Stack Unwinding?

小智 10

假设一个对象O由两个拥有资源的对象R和S组成.如果O被销毁会发生什么?

在带有RAII的C++中,对象可以拥有其他对象,这样一个对象的破坏必然会耦合到另一个对象.如果O 拥有 R和S - 通过按值存储它们,或者拥有依次拥有R和S的东西(unique_ptr,按值存储R和S的容器),那么O的破坏必然会破坏R和S.由于R和S的析构函数在它们之后正确清理,因此O不需要手动执行任何操作.

相反,C#对象没有所有者决定其生命周期何时结束.即使O被确定性地销毁(通常不是),R和S也可以通过另一个参考来达到.更重要的是,O引用R和S的方式与任何其他局部变量,对象字段,数组元素等引用R和S的方式相同.换句话说,没有办法表明所有权,因此计算机可以'吨决定当对象应该被破坏,并且当它是仅非所属/借用参考.当然你不希望这段代码关闭文件?

File f = GetAFile();
return f; // end of method, the reference f disappears
Run Code Online (Sandbox Code Playgroud)

但就CLR而言,f这里来自本地的引用与从O到R/S的引用完全相同.

TL; DR所有权.

  • @KubaOber 但 C# 没有,而且它缺乏添加合理的所有权模型的几个先决条件。这正是我回答的重点。 (2认同)