Sign in to follow this  

[.net] dispose and finalizers

This topic is 3460 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I read in a C++/CLI book that implementing a destructor (C++ kind, not C# kind) is the same as implementing IDisposable. Moreover, if the C++ destructor is called then it suppresses the finalizer. My experiments agree with this. However, the same does not seem to be true in C#: I see C# code where they call GC.SuppressFinalize(this) in the Dispose method. Why is it necessary to do this in C# but not C++/CLI. From my understanding, in C++/CLI, the destructor is just another way to implement IDisposable, so it should be the same... Does the C++/CLI compiler add GC.SuppressFinalize(this) at the end of every destructor?

Share this post


Link to post
Share on other sites
If you implement a "destructor" in C++/CLI, you are (more or less) only implementing IDisposable on this class. The code in the ~ClassName() method is called when someone calls Dispose() on this object (or rather delete theObject in C++/CLI). This is a huge difference to the "destructors" in C#, which implement the finalizer.

To implement a finalizer in C++/CLI you need this syntax:

!ClassName(){
// finalizer code here
}



Quote:
Original post by Quat
Does the C++/CLI compiler add GC.SuppressFinalize(this) at the end of every destructor?

Short: It does if the class has a finalizer (!ClassName()). The compiler uses a dispose pattern comparable to the one normally used for C# (Dispose() + Dispose(bool disposing)) Depending on whether you implemented ~ClassName() and/or !ClassName(), the C++/CLI will implement Dispose(bool disposing) slightly differently. Reflector can show you much better what the compiler does.

Here's a quick comparison of two roughly equivalent classes, one in C++/CLI, one in C#


// C++/CLI
public ref class MyResource{
public:
// "destructor" (dispose)
~MyResource(){
// Dispose managed resources
Console::WriteLine("C++/CLI: Disposing managed resources");

// dispose unmanaged resources as well
this->!MyResource();
}

// finalizer
!MyResource(){
// Dispose unmanaged resources
Console::WriteLine("C++/CLI: Disposing unmanaged resources");
}

};


C#
public class MyResource : IDisposable {
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}

~MyResource() {
Dispose(false);
}

protected virtual void Dispose(bool disposing) {
if (disposing) {
Console.WriteLine("C#: Disposing managed resource");
}

Console.WriteLine("C#: Disposing unmanaged resource");
}
}




For the C++/CLI case the compiler will create three extra methods:

public sealed override void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
{
if (flag1)
{
this.~MyResource();
}
else
{
try
{
this.!MyResource();
}
finally
{
base.Finalize();
}
}
}

protected override void Finalize()
{
this.Dispose(false);
}




Regards,
Andre

Share this post


Link to post
Share on other sites

This topic is 3460 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this