简体   繁体   English

如何从C#确定性地处理托管C ++ / CLI对象?

[英]How can I deterministically dispose of a managed C++/CLI object from C#?

I have a managed object in a C++/CLI assembly. 我在C ++ / CLI程序集中有一个托管对象。 Being C++/CLI, it implements the Disposable pattern through its "destructor" (yes, I'm aware it's not the same as a standard C++ destructor). 作为C ++ / CLI,它通过“析构函数”实现Disposable模式(是的,我知道它与标准C ++析构函数不同)。 From C++/CLI, I would simply delete the object. 从C ++ / CLI,我只想delete该对象。 However, I am using this object as a member variable in a C# class. 但是,我将此对象用作C#类中的成员变量。

From my C# class, then, I would like to call the equivalent of the Dispose() method on the C++/CLI object when I am finished using it. 从我的C#类开始,我想在使用它时调用C ++ / CLI对象上的Dispose()方法。 Since it is (and must be) a member variable of the class, utilizing a using() block is out of the question. 由于它是(并且必须是)类的成员变量,因此使用using()块是不可能的。 As far as I can tell, there is no exposed method for direct, deterministic disposal of resources from a language other than C++/CLI. 据我所知,没有公开的方法可以直接,确定地处理来自C ++ / CLI之外的语言的资源。 How can I accomplish this? 我怎么能做到这一点?

It is not so obvious in C++/CLI but it works exactly the way it does in C#. 它在C ++ / CLI中并不那么明显,但它的工作方式与C#中的方式完全相同 You can see it when you look at the class with Object Browser. 使用对象浏览器查看类时,您可以看到它。 Or a decompiler like ildasm.exe, best way to see what it does. 或者像ildasm.exe这样的反编译器,可以看到它的作用。

When you write the destructor then the C++/CLI compiler auto-generates a bunch of code. 编写析构函数时,C ++ / CLI编译器会自动生成一堆代码。 It implements the disposable pattern, your class automatically implements IDisposable, even though you didn't declare it that way. 它实现了一次性模式,你的类自动实现IDisposable,即使你没有这样声明它。 And you get a public Dispose() method, a protected Dispose(bool) method and an automatic call to GC::SuppressFinalize(). 你得到一个公共的Dispose()方法,一个受保护的Dispose(bool)方法和一个自动调用GC :: SuppressFinalize()。

You use delete in C++/CLI to explicitly invoke it, the compiler emits a Dispose() call. 您在C ++ / CLI中使用delete来显式调用它,编译器会发出Dispose()调用。 And you get the equivalent of RAII in C++/CLI by using stack semantics , the compiler automatically emits the Dispose call at the end of the scope block. 并且通过使用堆栈语义 ,您在C ++ / CLI中获得了等效的RAII,编译器会自动在范围块的末尾发出Dispose调用。 Syntax and behavior that's familiar to C++ programmers. C ++程序员熟悉的语法和行为。

You do the exact same thing you'd do in C# if the class would have been written in C#. 如果该类是用C#编写的,那么您在C#中执行的操作完全相同。 You call Dispose() to invoke explicitly, you use the using statement to invoke it implicitly in an exception-safe way. 您可以调用Dispose()来显式调用,使用using语句以异常安全的方式隐式调用它。

Same rules apply otherwise, you only need the destructor when you need to release something that is not managed memory. 否则,相同的规则适用,当您需要释放非托管内存的东西时,您只需要析构函数。 Almost always a native object, the one you allocated in the constructor. 几乎总是一个本机对象,即在构造函数中分配的对象。 Consider that it might not be worth the bother if that unmanaged object is small and that GC::AddMemoryPressure() is a very decent alternative. 如果非托管对象很小并且GC :: AddMemoryPressure()是一个非常不错的替代方案,请考虑它可能不值得。 You do however have to implement the finalizer ( !ClassName() ) in such a wrapper class. 但是,您必须在这样的包装类中实现终结器( !ClassName() )。 You cannot force external client code to call Dispose(), doing so is optional and it is often forgotten. 您不能强制外部客户端代码调用Dispose(),这样做是可选的,并且经常被遗忘。 You don't want such an oversight to cause an unmanaged memory leak, the finalizer ensures that it is still released. 您不希望这种疏忽导致非托管内存泄漏,终结器确保它仍然被释放。 Usually the simplest way to write the destructor is to explicitly call the finalizer ( this->!ClassName(); ) 通常,编写析构函数的最简单方法是显式调用终结器( this->!ClassName();

The C++/CLI destructor-like syntax automatically implements IDisposable , but it does so in a manner similar to C#'s explicit interface implementation . 类似C ++ / CLI析构函数的语法自动实现IDisposable ,但它以类似于C#的显式接口实现的方式实现 This means you'll have to cast to IDisposable to access the Dispose method: 这意味着您必须转换为IDisposable才能访问Dispose方法:

((IDisposable)obj).Dispose();

You can't. 你不能。 At least, not from C#. 至少,不是来自C#。 Let the garbage collector do its job. 让垃圾收集器完成它的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM