C# Destructor Blueprint

J

Joe

I am looking for the quintessential blueprint for how a
C++ like destructor should be implemented in C#. I see
all kinds of articles in print and on the web, but I see
lots of discrepencies. For example ...

C# Essentials (O'Reilly) - "Finalizers are class-only
methods". Not sure what "class-only method" means in this
context, but ususally I would assume that to mean it is
static and would only be called once for the life of the
program, and not once for every object of that class. Am
I reading this correctly? Is it just plain wrong? Will
the Finalize method be called once for every object?

Can an object's destructor/finalizer be called explicitly
by your code? Programming C# (O'Reilly) says no on page
80. Yet on MS site
(http://msdn.microsoft.com/library/default.asp?
url=/library/en-us/dncscol/html/deepc10192000.asp?
frame=true) they say yes, search for "One simple solution
is to make the finalizer calls explicit" on that page.

So, lets assume I have a handle to an unmanaged resource
(intentionally vague), where exactly should I put my code
to free/close the handle? In the Finalize() or Dispose()?

As you can see, I have a poor understanding of the proper
way to do this. I have read lots of articles, but cannot
find any that actually look correct to me.

Thanks.
 
P

Peter Rilling

The only real difference between the C++ destructor and the C#/.NET
destructor is that in .NET, you have not control over when the "finalizer"
is called.

I do not believe the C# compiler will let you call the Finalize method
directly, but other languages may.

In the destructor, you simply put whatever code you need to release
resources.

It may be a good idea to include both a destructor (Finalize) and a Dispose
method. What you would do is put the logic in the Dispose method and simply
have the Finalize method call the Dispose method. That way you can choose
to manually dispose of the resources, or wait for the GC to do it.

Destructors are instance specific just like normal constructors. They have
to be since the whole purpose is the resource resources that were allocated
within an object instance.
 
D

Daniel Pratt

Hi Joe,

Joe said:
I am looking for the quintessential blueprint for how a
C++ like destructor should be implemented in C#. I see
all kinds of articles in print and on the web, but I see
lots of discrepencies. For example ...

C# Essentials (O'Reilly) - "Finalizers are class-only
methods". Not sure what "class-only method" means in this
context, but ususally I would assume that to mean it is
static and would only be called once for the life of the
program, and not once for every object of that class. Am
I reading this correctly? Is it just plain wrong? Will
the Finalize method be called once for every object?

I'm not sure what "class-only" means in this case, but finalizers are
*not* static. If a finalizer has been defined for a class then it will be
called for every instance of that class unless it has been suppressed or in
other unusual circumstances (the app process is terminated, etc.).
Can an object's destructor/finalizer be called explicitly
by your code? Programming C# (O'Reilly) says no on page
80. Yet on MS site
(http://msdn.microsoft.com/library/default.asp?
url=/library/en-us/dncscol/html/deepc10192000.asp?
frame=true) they say yes, search for "One simple solution
is to make the finalizer calls explicit" on that page.

According to the docs on Object.Finalize, you may only explicitly call
the Finalize method of a base class.
So, lets assume I have a handle to an unmanaged resource
(intentionally vague), where exactly should I put my code
to free/close the handle? In the Finalize() or Dispose()?

This article covers the topic pretty well, I think:
http://tinyurl.com/2k6e (MSDN)

Basically a finalizer is an absolute last resort. Put your resource
deallocation code in another method and call it from either the Finalizer or
IDisposable.Dispose. Then the only other thing to do is to call
"GC.SuppressFinalize(this);" from IDisposable.Dispose so that the object
isn't "finalized" unnecessarily.

Regards,
Dan
 
R

Richard Grimes [MVP]

Joe said:
I am looking for the quintessential blueprint for how a
C++ like destructor should be implemented in C#. I see
all kinds of articles in print and on the web, but I see
lots of discrepencies. For example ...

Native C++ destructors are used to release resources, and they are called
when an object is deleted either explicitly (through the delete operator) or
when a stack allocated object goes out of scope. In general the stack
object's lifetime will be at maximum the scope of the method where the
variable is declared, but native C++ also allows global objects.

..NET does not have global objects, nor does it have stack allocated objects.
C# does not have a delete operator (C++ does, even for .NET objects).

The C# destructor provides the code for the Finalizer, in general you should
avoid implementing a Finalizer when you can. The reason is that you do not
know when the Finalizer will be called, it could be in a few minutes or in a
few hours. Native C++ destructors are generally used to release resources
used by an object, and the implication is that those resources may be needed
by other code, so you want them released as soon as possible. For this
reason Microsoft came up with the Dispose pattern and IDisposable: the
developer puts the code to release the resources in Dispose. Of course, that
does mean that the user has a responsibility to call Dispose, so you can
create a destructor (Finalizer) that calls Dispose because releasing
resources late is better than not releasing them at all.

However, this brings up some more problems. When the Finalizer is called has
Dispose already been called? When Dispose is called explicitly you can still
call methods on the object, so you could call methods that use resources
that are already disposed. A .NET object could have references to other .NET
objects that could hold resources, so it makes sense to dispose them too, or
does it?

The framework has a pattern which is used by Components. It works like this:
a class implements a protected version of Dispose (not a member of
IDisposable) which is a protected member of the class. This version has a
boolean parameter which is false if the method is called by the Finalizer.
The C# destructor should call this method with false and Dispose will then
only release unmanaged resources. The reason for this is because if this
object is being finalised then so will the objects that it has a reference
to. The class should then implement IDisposable.Dispose to call this method
with true. The protected Dispose method when it gets false as a method
should release both managed and unmanaged resources because there is no
guarantee how long it will be until the object will be finalized.
C# Essentials (O'Reilly) - "Finalizers are class-only
methods". Not sure what "class-only method" means in this
context, but ususally I would assume that to mean it is
static and would only be called once for the life of the
program, and not once for every object of that class. Am
I reading this correctly? Is it just plain wrong? Will
the Finalize method be called once for every object?

The Finalizer is called for each object unless the object calls
GC.SuppressFinalize(this)
Can an object's destructor/finalizer be called explicitly
by your code? Programming C# (O'Reilly) says no on page
80. Yet on MS site

The Finalizer is protected, so you cannot call it outside of the class (or
derived classes).
(http://msdn.microsoft.com/library/default.asp?
url=/library/en-us/dncscol/html/deepc10192000.asp?
frame=true) they say yes, search for "One simple solution
is to make the finalizer calls explicit" on that page.

Note the date: October 2000, that's while .NET was in beta: in the RTM you
cannot call the destructor (but you can in C++ said:
So, lets assume I have a handle to an unmanaged resource
(intentionally vague), where exactly should I put my code
to free/close the handle? In the Finalize() or Dispose()?

The Dispose(bool) method, as I have described above.
As you can see, I have a poor understanding of the proper
way to do this. I have read lots of articles, but cannot
find any that actually look correct to me.

That's OK, it would be more helpful to you if all the articles/books agreed
<g>

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top