在C#对象上调用C ++ / CLI删除

我正在将一些代码从C ++ / CLI转换为C#。 其中一个对象在C ++ / CLI版本中有一个析构函数。 其他一些C ++ / CLI代码在使用后调用此对象上的“delete”。

我需要在此对象的C#版本中实现哪种方法,以便那些“删除”继续运行相同的function(IDisposable.Dispose,终结器或其他我缺少的东西)?

我想说如果你需要确定性的资源处理, IDisposable接口就是你要找的。 这通常是非托管资源的情况,例如需要关闭的非托管句柄,流或数据库连接。

在C ++ / CLI中,如果声明托管类型( ref class等),则使用析构函数语法实现IDisposable ,并使用delete关键字调用Dispose() 。 如果在本地声明这样的托管类型对象(不使用^运算符或gcnew ),当对象超出范围时,C ++ / CLI甚至会自动为您调用Dispose() 。 这样,C ++ / CLI比C#更方便。

使用C#时,您将无法在对象上调用delete ,而是需要手动调用Dispose() 。 处理IDisposable对象的另一种方法是using块。

终结器(使用析构函数语法在C#中实现)与C ++析构函数不同,因为它在调用时不确定。 具有终结器的对象基本上排队,直到终结器线程决定调用它们的终结器,因此实际上你永远不知道何时调用它。

处理非托管资源的最佳方法可能是两者的结合。 请参阅此处了解建议的方法:
http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx

但请注意,在使用IDisposable ,即使您可以确定地处理非托管资源,仍然需要由垃圾收集器(非确定性地)收集托管对象。

我刚刚发现一篇文章解释了C ++ / CLI和C#之间的差异。 你可能会发现它很有趣:
http://weblogs.thinktecture.com/cnagel/2006/04/ccli-finalize-and-dispose.html

C ++ / CLI和C#之间存在术语不匹配。 C ++ / CLI析构函数(~Foo)是IDisposable.Dispose()方法实现。 C ++ / CLI类没有显式实现IDisposable,它只是存在析构函数而自动生成。

C ++ / CLI终结器(!Foo)是C#析构函数。

因此,C ++ / CLI 删除操作符等同于调用Dispose()方法。 注意C ++ / CLI中的堆栈语义,由没有^ hat的引用类型的局部变量触发。 编译器在作用域块的末尾生成对Dispose()的隐藏调用。 这相当于C# using关键字。 很难从源代码中看到,所以要特别注意或者用ildasm.exe查看生成的IL

C#不提供相同的工具,但它确实为您提供了模式:如果您的dtor正在关闭流,取消链接指针或正确设置状态,那么我觉得IDisposable接口非常合适:

 // C# void Dispose() { _stream.Close(); _ptr = null; _running = false; } // with obj.Dispose(); 

你不能真正强迫GC保持内存打开。 有一些方法可以帮助GC知道什么可以和应该被释放,请阅读http://msdn.microsoft.com/en-us/library/ee787088.aspx以获取更多信息。

请记住,使用IDisposable需要您适当地调用Dispose()方法。 因此,除了每次delete ,您还需要使用Dispose() 。 终结器的安全部分是当GC实际释放它时,它将被调用。 但是,您无法自己调用终结器(因此,如果删除/处置的时间很重要,那么这不是正确的解决方案。)

对我而言,这实际上取决于析构函数的作用。 如果它正在执行类似释放非托管资源(例如SQL或文件连接)的操作,那么我将实现IDispose并在Dispose()方法中关闭连接。

如果它正在销毁不需要任何显式清理的其他对象,那么我只是将析构函数保留下来并让GC处理它。