Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a managed object in a C++/CLI assembly. 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). From C++/CLI, I would simply delete the object. However, I am using this object as a member variable in a C# class.

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. Since it is (and must be) a member variable of the class, utilizing a using() block is out of the question. As far as I can tell, there is no exposed method for direct, deterministic disposal of resources from a language other than C++/CLI. How can I accomplish this?

like image 815
JimEvans Avatar asked Feb 08 '11 15:02

JimEvans


People also ask

How do you dispose an object in C++?

In C++, the operator delete destroys an object by calling its destructor, and then deallocates the memory where that object was stored. Occasionally, however, it is useful to separate those two operations. [1] Destroy calls an object's destructor without deallocating the memory where the object was stored.

How do you use the dispose method?

The Dispose(bool) method overloadThe disposing parameter should be false when called from a finalizer, and true when called from the IDisposable. Dispose method. In other words, it is true when deterministically called and false when non-deterministically called.

What happens if Dispose is not called?

Implement a finalizer to free resources when Dispose is not called. By default, the garbage collector automatically calls an object's finalizer before reclaiming its memory.

Does the garbage collector call Dispose?

The GC does not call Dispose , it calls your finalizer (which you should make call Dispose(false) ).


2 Answers

It is not so obvious in C++/CLI but it works exactly the way it does in 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.

When you write the destructor then the C++/CLI compiler auto-generates a bunch of code. It implements the disposable pattern, your class automatically implements IDisposable, even though you didn't declare it that way. And you get a public Dispose() method, a protected Dispose(bool) method and an automatic call to GC::SuppressFinalize().

You use delete in C++/CLI to explicitly invoke it, the compiler emits a Dispose() call. 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. Syntax and behavior that's familiar to C++ programmers.

You do the exact same thing you'd do in C# if the class would have been written in C#. You call Dispose() to invoke explicitly, you use the using statement to invoke it implicitly in an exception-safe way.

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. You do however have to implement the finalizer (!ClassName()) in such a wrapper class. You cannot force external client code to call Dispose(), doing so is optional and it is often forgotten. 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();)

like image 184
Hans Passant Avatar answered Oct 09 '22 11:10

Hans Passant


The C++/CLI destructor-like syntax automatically implements IDisposable, but it does so in a manner similar to C#'s explicit interface implementation. This means you'll have to cast to IDisposable to access the Dispose method:

((IDisposable)obj).Dispose();
like image 27
R. Martinho Fernandes Avatar answered Oct 09 '22 10:10

R. Martinho Fernandes