2011-02-08 39 views
11

我在C++/CLI程序集中有一个托管对象。作为C++/CLI,它通过其“析构函数”实现了Disposable模式(是的,我知道它与标准的C++析构函数不同)。从C++/CLI中,我只需要delete这个对象。但是,我将此对象用作C#类中的成员变量。如何确定性地处理来自C#的托管C++/CLI对象?

从我的C#类中,我想在完成使用它时调用C++/CLI对象上的Dispose()方法的等价物。由于它是(并且必须是)该类的成员变量,因此使用using()块是不可能的。据我所知,从C++/CLI以外的语言直接确定性地处理资源没有任何公开的方法。我怎样才能做到这一点?

+0

我不明白,[Dispose`]有什么问题(http://msdn.microsoft.com/en-us/ library/system.idisposable.dispose.aspx)方法?没有它就无法实现一次性模式。 – 2011-02-08 15:51:58

+1

C++/CLI类不公开`Dispose()`方法。它隐含在C++/CLI(如`〜MyClass`)的析构函数的语法中,但是当从C#引用对象时,您没有暴露的Dispose()方法,就像我所知道的那样。 – JimEvans 2011-02-08 15:54:19

回答

9

类似于C++/CLI析构函数的语法自动实现IDisposable,但它的操作方式类似于C#的explicit interface implementation。这意味着你必须转换为IDisposable访问Dispose方法:

((IDisposable)obj).Dispose(); 
-2

你不能。至少,不是来自C#。让垃圾收集器做好工作。

+0

当然可以。 C#甚至有一个关键字。 – 2011-02-08 16:01:49

9

这是不是在C++/CLI那么明显,但它的工作原理究竟它在C#的方式。您可以在使用对象浏览器查看课程时看到它。或者像ildasm.exe这样的反编译器,看看它有什么作用。

当你编写析构函数时,C++/CLI编译器会自动生成一堆代码。它实现了一次性模式,即使你没有这样声明,你的类也会自动实现IDisposable。你得到一个公共的Dispose()方法,一个受保护的Dispose(bool)方法和一个自动调用GC :: SuppressFinalize()。

在C++/CLI中使用delete来显式调用它,编译器会发出Dispose()调用。通过使用堆栈语义,您可以在C++/CLI中获得相当于RAII的结果,编译器会自动在范围块末尾发出Dispose调用。 C++程序员熟悉的语法和行为。

如果这个类是用C#编写的,那么你会在C#中做同样的事情。您可以调用Dispose()来显式调用,您可以使用using语句以隐式方式以异常安全的方式调用它。

否则相同的规则适用,您只需要需要析构函数,当您需要释放一些不受管理的内存时。几乎总是一个本地对象,即您在构造函数中分配的对象。考虑一下,如果这个非托管对象很小并且GC :: AddMemoryPressure()是一个非常体面的选择,它可能不值得费神。但是,您必须在这样的包装类中实现终结器(!ClassName())。你不能强制外部客户端代码调用Dispose(),这样做是可选的,并且经常被遗忘。你不希望这样的疏忽导致非托管内存泄漏,终结器确保它仍然被释放。通常编写析构函数的最简单的方法是明确调用终结器(this->!ClassName();