Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling C++/CLI delete on C# object

Tags:

c#

c++-cli

I'm in the middle of converting some code from C++/CLI to C#. One of the objects has a destructor in the C++/CLI version. Some other C++/CLI code calls "delete" on this object after use.

Which method do I need to implement in the C# version of this object so those "delete"s continue to function the same (IDisposable.Dispose, the finalizer, or something else that I'm missing)?

like image 844
Daniel Gabriel Avatar asked Apr 19 '12 17:04

Daniel Gabriel


2 Answers

I would say the IDisposable interface is what you look for if you need deterministic disposal of resources. This is usually the case with unmanaged resources, such as unmanaged handles that need to be closed, streams or database connections.

In C++/CLI, if you declare a managed type (ref class and the like), IDisposable is implemented using the destructor syntax, and Dispose() is called by using the delete keyword. If you declare such an object of a managed type locally (without using the ^ operator or gcnew), C++/CLI even automatically calls Dispose() for you when the object goes out of scope. In that way, C++/CLI is more convenient than C#.

You won't be able to call delete on the object when using C#, you'll need to call Dispose() manually on it instead. Another way to dispose of IDisposable objects is the using block.

The finalizer (implemented in C# by using destructor syntax) is not the same as a C++ destructor, since it is not deterministic when it will be called. Objects with a finalizer are basically queued until the finalizer thread decides to call their finalizer, so effectively you never know exactly when that is called.

The best approach for dealing with unmanaged resources is probably a combination of the two. See here for the recommended approach:
http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx

Note, however that when using IDisposable, even though you can dispose of unmanaged resources deterministically, managed objects still need to be collected by the garbage collector (non-deterministically).

I just found an article explaining the differences of this between C++/CLI and C#. You might find it interesting:
http://weblogs.thinktecture.com/cnagel/2006/04/ccli-finalize-and-dispose.html

like image 157
Botz3000 Avatar answered Oct 14 '22 13:10

Botz3000


There's a terminology mismatch between C++/CLI and C#. The C++/CLI destructor (~Foo) is the IDisposable.Dispose() method implementation. A C++/CLI class doesn't explicitly implement IDisposable, it is automatic from just the presence of a destructor.

The C++/CLI finalizer (!Foo) is the C# destructor.

So the C++/CLI delete operator is equivalent to calling the Dispose() method. Beware of stack semantics in C++/CLI, triggered by a local variable of a reference type without the ^ hat. The compiler generates a hidden call to Dispose() at the end of the scope block. Which is equivalent to the C# using keyword. Hard to see from the source code so pay extra attention or look at the generated IL with ildasm.exe

like image 4
Hans Passant Avatar answered Oct 14 '22 13:10

Hans Passant