Calling C++/CLI delete on C# object

大憨熊 提交于 2020-01-11 00:20:14

问题


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)?


回答1:


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




回答2:


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




回答3:


C# doesn't provide the same tools, but it does provide patterns for you: If your dtor is closing a stream, unlinking pointers, or setting states appropriately then I feel the IDisposable interface is a good fit:

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

// with

obj.Dispose();

You can't really force GC to keep memory open. There are ways to help the GC know what can and should be freed, Read http://msdn.microsoft.com/en-us/library/ee787088.aspx for more info.

Keep in mind that using IDisposable expects you to call the Dispose() method appropriately. So in place of each delete, you would want to use Dispose(). The safe part of a finalizer is that when the GC is actually freeing it, it'll be called. However, you can't call the finalizer yourself (so if timing on delete/dispose is important, that isn't the right solution.)




回答4:


To me, it really depends on what the destructor is doing. If it's doing something like releasing an unmanaged resource (SQL or file connections, for example), then I would implement IDispose and close the connection in the Dispose() method.

If it's destroying other objects that do not require any explicit cleanup, then I would just leave the destructor out and let the GC handle it.



来源:https://stackoverflow.com/questions/10233710/calling-c-cli-delete-on-c-sharp-object

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!