Need explanation on calling Close() from finalizer.

K

Ken Varn

I read in the MSDN docs that you should not call any Close() method from a
connection object or data reader object from within a finalizer. I don't
quite understand why. Could someone explain?

--
-----------------------------------
Ken Varn
Senior Software Engineer
Diebold Inc.

EmailID = varnk
Domain = Diebold.com
-----------------------------------
 
J

John M Deal

I'm not a C++ guy but my guess is its because there is no deterministic
finalization in .Net due to the garbage collector so you can't rely on
when it will get called. If you want this type of functionality I'd
implement the IDisposable interface and place the "just in case" close
of a connection in the dispose method and call that if necessary from
your finalizer. This allows the user of your object to manage the
disposal if they use the disposal functionality properly and you to
handle the "just in case" if they don't.

That said you probably should consider making sure that you close your
connection as soon as you are done using it (rather than relying on
object destruction) so you don't accidentally bleed connections by
hoping your finalizer will someday be called when the garbage collector
gets around to it. If designed properly you won't usually see enough of
performance hit from doing this as you might think and it keeps
everything as clean and available as possible. Hope that helps.

Have A Better One!

John M Deal, MCP
Necessity Software
 
K

Ken Varn

This is the one area about .NET that sort of bothers me.

In C++, destructors work very well for cleaning up an object so that the
consumer of the object does not have to be concerned with doing cleanup.
Hence, in the spirit of .NET, garbage collection is what makes this
philosophy even more positive by automating memory management. However,
because of the way garbage collection is done in .NET, it now cancels out
the destructor philosophy of object cleanup being up to the object itself.
It now places that role back onto the object consumer and thus removes a
layer of encapsulation. If an object consumer does not remember to call a
Dispose() method, it could impact the application's ability to run
effectively. For C++ programmers, this is equivalent to having to call
delete after newing an object (the exact thing that garbage collection was
intended to prevent). But instead of having to delete an object, the
consumer must now have to call Dispose(). Seems like the GC solution solved
one problem, but created another.

Don't want to sound like a .NET basher. I use it a lot and love it.
However, there are some parts of it that seem like a step backward. Maybe I
am over complicating this. If anyone has further input on the subject, I
would appreciate some comments.



--
-----------------------------------
Ken Varn
Senior Software Engineer
Diebold Inc.

EmailID = varnk
Domain = Diebold.com
-----------------------------------
 
C

Chris Lyon [MSFT]

Hi Ken

.NET's Garbage Collector, like you've stated, automated memory management, relieving the developer of the need to explicitly delete objects. What the GC does not do (nor
has it ever claimed to do) is clean up unmanaged resources (database collections, file handles, etc). The developer must explicitly clean up these resources, usually through
the Dispose pattern. Note, calling Dispose is only necessary if an object holds unmanaged resources.

Hope that makes sense
-Chris

--------------------
This is the one area about .NET that sort of bothers me.

In C++, destructors work very well for cleaning up an object so that the
consumer of the object does not have to be concerned with doing cleanup.
Hence, in the spirit of .NET, garbage collection is what makes this
philosophy even more positive by automating memory management. However,
because of the way garbage collection is done in .NET, it now cancels out
the destructor philosophy of object cleanup being up to the object itself.
It now places that role back onto the object consumer and thus removes a
layer of encapsulation. If an object consumer does not remember to call a
Dispose() method, it could impact the application's ability to run
effectively. For C++ programmers, this is equivalent to having to call
delete after newing an object (the exact thing that garbage collection was
intended to prevent). But instead of having to delete an object, the
consumer must now have to call Dispose(). Seems like the GC solution solved
one problem, but created another.

Don't want to sound like a .NET basher. I use it a lot and love it.
However, there are some parts of it that seem like a step backward. Maybe I
am over complicating this. If anyone has further input on the subject, I
would appreciate some comments.



--
-----------------------------------
Ken Varn
Senior Software Engineer
Diebold Inc.

EmailID = varnk
Domain = Diebold.com


--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.
 
K

Ken Varn

I understand the idea behind memory management of the GC. What I don't
understand is why .NET classes cannot clean up their unmanaged resources
themselves when they are collected through their destructor methods (or
finalizers, whatever they are called). Classes in C++ implement destructors
to do cleanup when they go out of scope. The user of any objects
instantiated from that class do not have to explicitly call a cleanup
methods of that object. The object does cleanup on its own when it is
destroyed.

Thus, I don't understand why .NET classes that require cleanup of unmanaged
resources need an IDisposable interface that the user must explicitly call
before the object is garbage collected. Why not just put it in a destructor
or finalize and have the GC call it? Maybe this is already done, but I
don't understand why there is always an emphasis to call Dispose() on
objects such as a SQLConnection(), when it should do it on its own when it
is finalized.

--
-----------------------------------
Ken Varn
Senior Software Engineer
Diebold Inc.

EmailID = varnk
Domain = Diebold.com
-----------------------------------
"Chris Lyon [MSFT]" said:
Hi Ken

NET's Garbage Collector, like you've stated, automated memory management,
relieving the developer of the need to explicitly delete objects. What the
GC does not do (nor
has it ever claimed to do) is clean up unmanaged resources (database
collections, file handles, etc). The developer must explicitly clean up
these resources, usually through
the Dispose pattern. Note, calling Dispose is only necessary if an
object holds unmanaged resources.
Hope that makes sense
-Chris
rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this
message are best directed to the newsgroup/thread from which they
originated.
 
J

Jon Skeet [C# MVP]

I understand the idea behind memory management of the GC. What I don't
understand is why .NET classes cannot clean up their unmanaged resources
themselves when they are collected through their destructor methods (or
finalizers, whatever they are called).

Because that may well not be soon enough. For instance, if you open a
FileStream on a file, and let the garbage collector call the finalizer
for the FileStream, you may well find that another piece of code which
opens the same file fails - but only some of the time. Hardly ideal, is
it?
Classes in C++ implement destructors
to do cleanup when they go out of scope. The user of any objects
instantiated from that class do not have to explicitly call a cleanup
methods of that object. The object does cleanup on its own when it is
destroyed.

Yes, but that's because C++ has deterministic destructors - at the cost
of GC. Basically you can have one or the other, but not both.
Thus, I don't understand why .NET classes that require cleanup of unmanaged
resources need an IDisposable interface that the user must explicitly call
before the object is garbage collected. Why not just put it in a destructor
or finalize and have the GC call it? Maybe this is already done, but I
don't understand why there is always an emphasis to call Dispose() on
objects such as a SQLConnection(), when it should do it on its own when it
is finalized.

Suppose you've got a connection pool of 10 connections. Suppose you do
10 things which don't generate much garbage, and you don't close or
dispose the connection - suddenly you're out of connections until the
garbage collector next runs.
 
C

Chris Lyon [MSFT]

Jon is absolutely right. Due to the nondeterministic nature of the GC, your object may be holding on to that unmanaged resource for a long time until it is finalized.

In addition, objects that implement finalizers aren't immediately collected, rather they are promoted a generation, as well as any objects they reference. This is bad for
performance, since objects are going to remain in memory for longer than you need.

Also, there is no guarantee that finalizers will even be run, although such circumstances are specific and rare.

Microsoft's guidelines with respect to finalizers:
-don't use them unless you have unmanaged resources
-if you do have unmanaged resources, use the Dispose pattern, saving finalizers for the exceptional case where Dispose was (accidentally) not called.

-Chris

--------------------
Because that may well not be soon enough. For instance, if you open a
FileStream on a file, and let the garbage collector call the finalizer
for the FileStream, you may well find that another piece of code which
opens the same file fails - but only some of the time. Hardly ideal, is
it?


Yes, but that's because C++ has deterministic destructors - at the cost
of GC. Basically you can have one or the other, but not both.


Suppose you've got a connection pool of 10 connections. Suppose you do
10 things which don't generate much garbage, and you don't close or
dispose the connection - suddenly you're out of connections until the
garbage collector next runs.


--

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this message are best directed to the newsgroup/thread from which they originated.
 
K

Ken Varn

I can understand the reasoning behind your argument, I just feel that it is
somewhat of a compromise for automated memory management that is hard to
swallow after being accustomed to having it with unmanaged C++ stack
allocated objects.

Maybe I want my cake and eat it too, but it just bothers me that I may have
some lingering resource that some object may create and does not have the
ability to clean up adequately on its own without me having to explicitly
call some cleanup method. Too bad there is not some way to declare a .NET
object as a stack reference so that it immediately gets cleaned up when the
implementing function goes out of scope. I know that this opens a whole can
of worms because of reference pointers, object passing, etc.. I just miss
having automated object cleanup from my experiences with unmanaged C++.

--
-----------------------------------
Ken Varn
Senior Software Engineer
Diebold Inc.

EmailID = varnk
Domain = Diebold.com
 
J

Jon Skeet [C# MVP]

I can understand the reasoning behind your argument, I just feel that it is
somewhat of a compromise for automated memory management that is hard to
swallow after being accustomed to having it with unmanaged C++ stack
allocated objects.

Maybe I want my cake and eat it too, but it just bothers me that I may have
some lingering resource that some object may create and does not have the
ability to clean up adequately on its own without me having to explicitly
call some cleanup method. Too bad there is not some way to declare a .NET
object as a stack reference so that it immediately gets cleaned up when the
implementing function goes out of scope. I know that this opens a whole can
of worms because of reference pointers, object passing, etc.. I just miss
having automated object cleanup from my experiences with unmanaged C++.

Just as I'd miss automated heap-based cleanup if I started using
unmanaged C++ :)

It's basically a trade-off. I use memory resources far more often than
unmanaged resources, so it's one I'm comfortable with - I don't have to
keep track of who's using what data and whether there are cyclic
references etc, I just need to keep track of unmanaged resources. The
vast majority of the time that I'm using unmanaged resources, I can use
a simple "using" statement in C# to clean up after myself.
 

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