Using C#.NET 4.0
My company's application makes use of a resource locker to keep records from being edited simultaneously. We use the database to store the start time of a lock as well as the user who acquired the lock. This has led to the following (strange?) implementation of dispose on the resource locker, which happens to be called from a destructor:
protected virtual void Dispose(bool disposing)
{
lock (this)
{
if (lockid.HasValue)
{
this.RefreshDataButtonAction = null;
this.ReadOnlyButtonAction = null;
try
{
**Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("#lockID", lockid.Value);
parameters.Add("#readsToDelete", null);
Object returnObject = dbio2.ExecuteScalar("usp_DeleteResourceLockReads", parameters);**
lockid = null;
}
catch (Exception ex)
{
Logger.WriteError("ResourceLockingController", "DeleteResourceLocks", ex);
}
finally
{
((IDisposable)_staleResourcesForm).Dispose();
_staleResourcesForm = null;
}
}
}
}
I am concerned about the bolded section we because have been logging strange "Handle is not initialized" exceptions from the database call. I read elsewhere that it is not safe to create new objects during Finalize(), but does the same rule apply to dispose()? Are there any possible side effects that accompany creating new objects during Dispose()?
which happens to be called from a destructor
That's the real problem. You cannot assume that the *dbio2" object hasn't been finalized itself. Finalization order is not deterministic in .NET. The outcome would look much like you describe, an internal handle used by the dbase provider will have been released so a "Handle is not initialized" exception is expected. Or the dbio2 object was simply already disposed.
This is especially likely to go wrong at program exit. You'll then also have problem when the 2 second timeout for the finalizer thread, a dbase operation can easily take more.
You simply cannot rely on a finalizer to do this for you. You must check the disposing argument and not call the dbio2.ExecuteScalar() method when it is false. Which probably ends the usefulness of the destructor as well.
Dispose is just a method, like any other method. There are some conventions about things that it should/shouldn't do, but there's nothing from the system's perspective that is wrong with creating objects in a Dispose call.
Making a DB call is a bit concerning to be personally; I wouldn't expect such an expensive and error prone activity to be called in a Dispose method, but that's more of a convention/expectation. The system won't have a problem with that.
Yes, but I would not do so unless the object created is within the local scope of the method. IDisposable is an advertisement that this class has some resource (often an unmanaged resource) that should be freed when the object is no longer used. If your Dispose is being called by your finializer (ie you are not calling the destructor directly, but waiting for the GC to do it) it can be an indication that you should be calling it earlier. You never know when the C# destructor will run, so you may be unnecessarily tying up that resource. It could also be in indication that your class doesn't need to implement IDisposable.
In your case your are using object dbio2 which I assume represents your DB connection. However, since this is called from the destructor how do you know if your connection is still valid? You destructor could an hour after your connection has been lost. You should try to ensure that this Dispose is called while you know the dbio2 object is still in scope.
Related
TL;DR -- Is it ever appropriate to execute business logic in IDisposable.Dispose?
In my search for an answer, I read through the question: Is it abusive to use IDisposable and "using" as a means for getting "scoped behavior" for exception safety? It came very close to addressing this issue, but I'd like to attack it dead on. I recently encountered some code that looked like this:
class Foo : IDisposable
{
public void Dispose()
{
ExecuteSomeBusinessBehavior();
NormalCleanup();
}
}
and is used in a context such as:
try
{
using (var myFoo = new Foo())
{
DoStuff();
foo.DoSomethingFooey();
...
DoSomethingElse();
Etc();
}
}
catch (Exception ex)
{
// Handle stuff
}
Upon seeing this code I immediately began to itch. Here's what I see when I look at this code:
First, looking at just the usage context, it's not remotely apparent that actual business logic, not just cleanup code, will be executed when the code leaves the using scope.
Second, if any of the code within the "using" scope throws an exception, the business logic in the Dispose method will still execute and does so before the Try/Catch can handle the exception.
My questions to the StackOverflow community are these: Does it ever make sense to put business logic in the IDisposable.Dispose method? Is there a pattern that achieves similar results without making me itch?
(Sorry, this is more of a comment, but it exceeds the comment length limit.)
Actually, there is an example in the .NET framework where IDisposable is used to create a scope and do useful work when disposing: TransactionScope.
To quote from TransactionScope.Dispose:
Calling this method marks the end of the transaction scope. If the TransactionScope object created the transaction and Complete was called on the scope, the TransactionScope object attempts to commit the transaction when this method is called.
If you decide to take that route, I would suggest that
you make it blatantly obvious that your object creates a scope, e.g., by calling it FooScope instead of Foo and
you think very hard about what should happen when an exception causes the code to leave your scope. In TransactionScope, the pattern of calling Complete at the end of the block ensures that Dispose can distinguish between the two cases.
The real meaning of IDisposable is that an object knows of something, somewhere which has been put into a state that should be cleaned up, and it has the information and impetus necessary to perform such cleanup. Although the most common "states" associated with IDisposable are things like files being open, unmanaged graphic objects being allocated, etc. those are only examples of uses, and not a definition of "proper" use.
The biggest issue to consider when using IDisposable and using for scoped behavior is that there is no way for the Dispose method to distinguish scenarios where an exception is thrown from a using block from those where it exits normally. This is unfortunate, since there are many situations where it would be useful to have scoped behavior which was guaranteed to have one of two exit paths depending upon whether the exit was normal or abnormal.
Consider, for example, a reader-writer lock object with a method that returns an IDisposable "token" when the lock is acquired. It would be nice to say:
using (writeToken = myLock.AcquireForWrite())
{
... Code to execute while holding write lock
}
If one were to manually code the acquisition and release of the lock without a try/catch or try/finally lock, an exception thrown while the lock was held would cause any code that was waiting on the lock to wait forever. That is a bad thing. Employing a using block as shown above will cause the lock to be released when the block exits, whether normally or via exception. Unfortunately, that may also be a bad thing.
If an unexpected exception is thrown while a write-lock is held, the safest course of behavior would be to invalidate the lock so that any present or future attempt to acquire the lock will throw an immediate exception. If the program cannot usefully proceed without the locked resource being usable, such behavior would cause it to shut down quickly. If it can proceed e.g. by switching to some alternate resource, invalidating the resource will allow it to get on with that much more effectively than would leaving the lock uselessly acquired. Unfortunately, I don't know of any nice pattern to accomplish that. One could do something like:
using (writeToken = myLock.AcquireForWrite())
{
... Code to execute while holding write lock
writeToken.SignalSuccess();
}
and have the Dispose method invalidate the token if it's called before success has been signaled, but an accidental failure to signal the success could cause the resource to become invalid without offering indication as to where or why that happened. Having the Dispose method throw an exception if code exits a using block normally without calling SignalSuccess might be good, except that throwing an exception when it exits because of some other exception would destroy all information about that other exception, and there's no way Dispose can tell which method applies.
Given those considerations, I think the best bet is probably to use something like:
using (lockToken = myLock.CreateToken())
{
lockToken.AcquireWrite(Describe how object may be invalid if this code fails");
... Code to execute while holding write lock
lockToken.ReleaseWrite();
}
If code exits without calling ReleaseWrite, other threads that try to acquire the lock will receive exceptions that include the indicated message. Failure to properly manually pair the AcquireWrite and ReleaseWrite will leave the locked object unusable, but not leave other code waiting for it to become usable. Note that an unbalanced AcquireRead would not have to invalidate the lock object, since code inside the read would never put the object into an invalid state.
Business logic code should never be written in any circumstances to Dispose method reason is, you are relying on a unreliable path. What if user does not call your dispose method? You missed to call a complete functionality ? What if there was an exception thrown in the method call of your dispose method? And why would you perform a business operation when user is asking to dispose the object itself. So logically, technically it should not be done.
I'm currently reading Introduction to Rx, by Lee Campbell, and it has a chapter called IDisposable, where he explicitly advocates taking advantage of the integration with the using construct, in order to "create transient scope".
Some key quotations from that chapter:
"If we consider that we can use the IDisposable interface to effectively create a scope, you can create some fun little classes to leverage this."
(...see examples below...)
"So we can see that you can use the IDisposable interface for more than just common use of deterministically releasing unmanaged resources. It is a useful tool for managing lifetime or scope of anything; from a stopwatch timer, to the current color of the console text, to the subscription to a sequence of notifications.
The Rx library itself adopts this liberal usage of the IDisposable interface and introduces several of its own custom implementations:
BooleanDisposable
CancellationDisposable
CompositeDisposable
ContextDisposable
MultipleAssignmentDisposable
RefCountDisposable
ScheduledDisposable
SerialDisposable
SingleAssignmentDisposable"
He gives two fun little examples, indeed:
Example 1 - Timing code execution. "This handy little class allows you to create scope and measure the time certain sections of your code base take to run."
public class TimeIt : IDisposable
{
private readonly string _name;
private readonly Stopwatch _watch;
public TimeIt(string name)
{
_name = name;
_watch = Stopwatch.StartNew();
}
public void Dispose()
{
_watch.Stop();
Console.WriteLine("{0} took {1}", _name, _watch.Elapsed);
}
}
using (new TimeIt("Outer scope"))
{
using (new TimeIt("Inner scope A"))
{
DoSomeWork("A");
}
using (new TimeIt("Inner scope B"))
{
DoSomeWork("B");
}
Cleanup();
}
Output:
Inner scope A took 00:00:01.0000000
Inner scope B took 00:00:01.5000000
Outer scope took 00:00:02.8000000
Example 2 - Temporarily changing console text color
//Creates a scope for a console foreground color. When disposed, will return to
// the previous Console.ForegroundColor
public class ConsoleColor : IDisposable
{
private readonly System.ConsoleColor _previousColor;
public ConsoleColor(System.ConsoleColor color)
{
_previousColor = Console.ForegroundColor;
Console.ForegroundColor = color;
}
public void Dispose()
{
Console.ForegroundColor = _previousColor;
}
}
Console.WriteLine("Normal color");
using (new ConsoleColor(System.ConsoleColor.Red))
{
Console.WriteLine("Now I am Red");
using (new ConsoleColor(System.ConsoleColor.Green))
{
Console.WriteLine("Now I am Green");
}
Console.WriteLine("and back to Red");
}
Output:
Normal color
Now I am Red
Now I am Green
and back to Red
I'm getting in nerve between dispose and finalize. Here is my example code:
public class Car:IDisposable
{
public string name;
public Car()
{
name = "My Car";
}
public void Dispose()
{
Console.WriteLine("This object has been disposed");
}
}
public static void Main()
{
Car anotherCar;
using (var car = new Car())
{
anotherCar = car;
Console.WriteLine("Before dispose. Name is: "+anotherCar.name);
}
Console.WriteLine("After dispose. Name is: "+anotherCar.name);
}
The result is:
Before dispose. Name is My Car
This object has been disposed
After dispose. Name is My Car
My question is : because C# will automatically dispose object after using{}, so I think at line "After dispose". anotherCar.name must be NULL. why it still be "My Car" ?
And my another question is : my book said that you shouldn't use GC.Collect() for some reason and one of these is Performance. So, who dispose object ? If that is Garbage Collector,too so I think dipose() has the same performance issues with finalizer()
Thanks :)
I think you are misunderstanding what Dispose actually does. It doesn't destroy your object, set anything to null, or otherwise perform any sort of magic. When you use the using statement, that just guarantees that Dispose will be called. What you do in your Dispose method is what determines the behavior of your object. Not the language or .NET framework.
If you look at the code again you will realize immediately that simply putting a Dispose() method on a class and implementing IDisposable does not add any behind the scenes magic, it is just a normal method with the added convenience that it will be called at the end of an using statement.
Generally in the Dispose method you should take care of clearing any (unmanaged) resources you want freed by yourself, for example closing a db connection or a file which was open for reading/saving...
Microsoft has a nice help page about implementing IDisposable correctly.
An object in .net is generally a combination of a type reference and the public and private fields required by that type (there are a few special cases like arrays and strings). Once created, an object in .net will continue to exist as long as some form of reference to it exists. Once there are no longer any references to an object, if will effectively cease to exist; any memory it had occupied will simply be unused memory, eligible for reuse at the next garbage collection.
The purpose of Dispose is not to destroy an object, but rather to allow an object to perform necessary actions with things outside itself before it disappears. As a simple example, suppose an object asks a remote server to grant it exclusive access to a file; the server supplies a token, with a promise that access will only be granted to code supplying that token. If the object were to simply disappear, the external server would leave the file locked for the exclusive use of code that holds a token that no longer exists. In other words, the file would be forever(*) unusable by anyone. Adding a Dispose method to the object which asked for the token would allow the object to sent the server an "Okay--I'm done with file XYZ1493" message, thus making the file available to other entities.
Note that the Dispose method doesn't actually destroy the file object. It may prompt the object to erase some of the data stored in its fields, but the object will continue to exist as long as any reference to it exists, and will cease to exist thereafter. There are some cases where calling Dispose on an object may hasten the demise of the object itself, by asking other outside objects which hold references to it to destroy those references. Even in those cases, however, the purpose of Dispose is to allow objects to issue requests to other things.
The question I have might be more to do with semantics than with the actual use of IDisposable. I am working on implementing a singleton class that is in charge of managing a database instance that is created during the execution of the application. When the application closes this database should be deleted.
Right now I have this delete being handled by a Cleanup() method of the singleton that the application calls when it is closing. As I was writing the documentation for Cleanup() it struck me that I was describing what a Dispose() method should be used for i.e. cleaning up resources. I had originally not implemented IDisposable because it seemed out of place in my singleton, because I didn't want anything to dispose the singleton itself. There isn't currently, but in the future might be a reason that this Cleanup() might be called but the singleton should will need to still exist. I think I can include GC.SuppressFinalize(this); in the Dispose method to make this feasible.
My question therefore is multi-parted:
1) Is implementing IDisposable on a singleton fundamentally a bad idea?
2) Am I just mixing semantics here by having a Cleanup() instead of a Dispose() and since I'm disposing resources I really should use a dispose?
3) Will implementing 'Dispose()' with GC.SuppressFinalize(this); make it so my singleton is not actually destroyed in the case I want it to live after a call to clean-up the database.
Implementing IDisposable for singleton might be good idea if you use a CAS techinque instead of locks to create a singleton. Something like this.
if (instance == null) {
var temp = new Singleton();
if (Interlocked.CompareExchange(ref instance, temp, null) != null) &&
temp is IDisposable) {
((IDisposable)temp).Dispose();
}
}
return instance
We created a temporary object and tried atomic Compare-and-Swap so we need to dispose this temporary object if it impletents IDisposable and it wasn't written to instance's location.
It might be good to avoid locks but also it's a bit overhead if some heavy logic is used to create a singleton's instance in its constructor.
If you don't want other code to cleanup or dispose your object just don't provide any opportunity for this. However, it might be good idea to provide some kind of reset() method to allow singleton to recreate itself if, let say, you use a lazy init. Something like this:
public static Singletong GetInstance() {
if (instance == null) {
instance = new Singleton(); //here we re-evalute cache for example
}
return instance
}
public static void Reset() {
instance = null;
}
In short, if you have a singleton and you call dispose. Any time that any object tries to use it after that, will be using an object in a disposed state.
Now putting it in, and disposing of the object after the application is done with it, isn't necessarily bad. You do have to be careful though when you call it. If you are really concerned with the cleanup and you have only one reference to it, you can put the clean up code in the objects finalizer ~YourClass that way it will only be called with .Net is sure it is no longer needed (when the application closes, if it is a true singleton).
Am I just mixing semantics here by
having a Cleanup() instead of a
Dispose() and since I'm disposing
resources I really should use a
dispose?
Yes, this is just semantics. Dispose is the standard for showing there are things that need to be cleared up after the program is done with the object.
Will implementing 'Dispose()' with
GC.SuppressFinalize(this); make it so
my singleton is not actually destroyed
in the case I want it to live after a
call to clean-up the database.
No what this means is that when you call the dispose method, the Garbage Collector won't call the object's custom finalizer.
I agree with Kevin's answer, but like to add something to this. I'm a bit confused about your statement:
When the application closes this
database should be deleted.
Do you really mean deleted? As in destroyed? Are you talking about a real (SQL) database?
You must understand that even if you put your clean up code in a finalizer, or in the Application_End event (ASP.NET) there is no way you can guarantee these are called. The process can be terminated, or the computer loses power. It seems more reasonable to delete the database on application startup, or at least have a fallback mechanism at startup with some cleanup.
While the finalizer would be a good place to put cleanup when dealing with resources, in your case we're talking about an application resource. What I mean by this is that the resource isn't perhaps bound to a single object (your singleton) but is part of the whole application. This can get a bit an abstract discussion, and it's perhaps more a matter of view.
What I'm trying to say it that when you see that database as a application resource, you will have to have your initialization and cleanup not bound to an object, but to the application. In an ASP.NET application this would be Application_Start and Application_End (global.asax). In an Windows Forms application, this would be Program.Main.
Still, when using these mechanisms over finalizers, you have no certainty that your clean up code will execute.
I've been debugging some code recently that was a bit memory leaky. It's a long running program that runs as a Windows service.
If you find a class wearing an IDisposable interface, it is telling you that some of the resources it uses are outside the abilities of the garbage collector to clean up for you.
The reason it is telling you this is that you, the user of this object, are now responsible for when these resources are cleaned up. Congratulations!
As a conscientious developer, you are nudged towards calling the .Dispose() method when you've finished with the object in order to release those unmanaged resources.
There is the nice using() pattern to help clean up these resources once they are finished with. Which just leaves finding which exact objects are causing the leakyness?
In order to aid tracking down these rogue unmanaged resources, is there any way to query what objects are loitering around waiting to be Disposed at any given point in time?
There shouldn't be any cases where you don't want to call Dispose, but the compiler cannot tell you where you should call dispose.
Suppose you write a factory class which creates and returns disposable objects. Should the compiler bug you for not calling Dispose when the cleanup should be the responsibility of your callers?
IDisposable is more for making use of the using keyword. It's not there to force you to call Dispose() - it's there to enable you to call it in a slick, non-obtrusive way:
class A : IDisposable {}
/// stuff
using(var a = new A()) {
a.method1();
}
after you leave the using block, Dispose() is called for you.
"Is there any way to detect at the end of the program which objects are loitering around waiting to be Disposed?"
Well, if all goes well, at the end of the program the CLR will call all object's finalizers, which, if the IDisposable pattern was implemented properly, will call the Dispose() methods. So at the end, everything will be cleared up properly.
The problem is that if you have a long running program, chances are some of your IDiposable instances are locking some resources that shouldn't be locked. For cases like this, user code should use the using block or call Dispose() as soon as it is done with an object, but there's really no way for a anyone except the code author to know that.
You are not required to call the Dispose method. Implementing the IDisposable interface is a reminder that your class probably is using resources such as a database connection, a file handle, that need to be closed, so GC is not enough.
The best practice AFAIK is to call Dispose or even better, put the object in a using statement.
A good example is the .NET 2.0 Ping class, which runs asynchronously. Unless it throws an exception, you don't actually call Dispose until the callback method. Note that this example has some slightly weird casting due to the way Ping implements the IDisposable interface, but also inherits Dispose() (and only the former works as intended).
private void Refresh( Object sender, EventArgs args )
{
Ping ping = null;
try
{
ping = new Ping();
ping.PingCompleted += PingComplete;
ping.SendAsync( defaultHost, null );
}
catch ( Exception )
{
( (IDisposable)ping ).Dispose();
this.isAlive = false;
}
}
private void PingComplete( Object sender, PingCompletedEventArgs args )
{
this.isAlive = ( args.Error == null && args.Reply.Status == IPStatus.Success );
( (IDisposable)sender ).Dispose();
}
Can I ask how you're certain that it's specifically objects which implement IDisposable? In my experience the most-likely zombie objects are objects which have not properly had all their event handlers removed (thereby leaving a reference to them from another 'live' object and not qualifying them as unreachable during garbage collection).
There are tools which can help track these down by taking a snapshot of the managed heap and stacks and allowing you to see what objects are considered in-use at a given point in time. A freebie is windbg using sos.dll; it'll take some googling for tutorials to show you the commands you need--but it works and it's free. A more user-friendly (don't confused that with "simple") option is Red Gate's ANTS Profiler running in Memory Profiling mode--it's a slick tool.
Edit: Regarding the usefulness of calling Dispose--it provides a deterministic way to cleanup objects. Garbage Collection only runs when your app has ran out of its allocated memory--it's an expensive task which basically stops your application from executing and looks at all objects in existance and builds a tree of "reachable" (in-use) objects, then cleans up the unreachable objects. Manually cleaning up an object frees it before GC ever has to run.
Because the method creating the disposable object may be legitimately returning it as a value, that is, the compiler can't tell how the programming is intending to use it.
What if the disposable object is created in one class/module (say a factory) and is handed off to a different class/module to be used for a while before being disposed of? That use case should be OK, and the compiler shouldn't badger you about it. I suspect that's why there's no compile-time warning---the compiler assumes the Dispose call is in another file.
Determining when and where to call Dispose() is a very subjective thing, dependent on the nature of the program and how it uses disposable objects. Subjective problems are not something compilers are very good at. Instead, this is more a job for static analysis, which is the arena of tools like FxCop and StyleCop, or perhaps more advanced compilers like Spec#/Sing#. Static analysis uses rules to determine if subjective requirements, such as "Always ensure .Dispose() is called at some point.", are met.
I am honestly not sure if any static analyzers exist that are capable of checking whether .Dispose() is called. Even for static analysis as it exists today, that might be a bit on the too-subjective side of things. If you need a place to start looking, however, "Static Analysis for C#" is probably the best place.
I've got a C# class with a Dispose function via IDisposable. It's intended to be used inside a using block so the expensive resource it handles can be released right away.
The problem is that a bug occurred when an exception was thrown before Dispose was called, and the programmer neglected to use using or finally.
In C++, I never had to worry about this. The call to a class's destructor would be automatically inserted at the end of the object's scope. The only way to avoid that happening would be to use the new operator and hold the object behind a pointer, but that required extra work for the programmer isn't something they would do by accident, like forgetting to use using.
Is there any way to for a using block to be automatically used in C#?
Many thanks.
UPDATE:
I'd like to explain why I'm not accepting the finalizer answers. Those answers are technically correct in themselves, but they are not C++ style destructors.
Here's the bug I found, reduced to the essentials...
try
{
PleaseDisposeMe a = new PleaseDisposeMe();
throw new Exception();
a.Dispose();
}
catch (Exception ex)
{
Log(ex);
}
// This next call will throw a time-out exception unless the GC
// runs a.Dispose in time.
PleaseDisposeMe b = new PleaseDisposeMe();
Using FXCop is an excellent suggestion, but if that's my only answer, my question would have to become a plea to the C# people, or use C++. Twenty nested using statements anyone?
Where I work we use the following guidelines:
Each IDisposable class must have a finalizer
Whenever using an IDisposable object, it must be used inside a "using" block. The only exception is if the object is a member of another class, in which case the containing class must be IDisposable and must call the member's 'Dispose' method in its own implementation of 'Dispose'. This means 'Dispose' should never be called by the developer except for inside another 'Dispose' method, eliminating the bug described in the question.
The code in each Finalizer must begin with a warning/error log notifying us that the finalizer has been called. This way you have an extremely good chance of spotting such bugs as described above before releasing the code, plus it might be a hint for bugs occuring in your system.
To make our lives easier, we also have a SafeDispose method in our infrastructure, which calls the the Dispose method of its argument within a try-catch block (with error logging), just in case (although Dispose methods are not supposed to throw exceptions).
See also: Chris Lyon's suggestions regarding IDisposable
Edit:
#Quarrelsome: One thing you ought to do is call GC.SuppressFinalize inside 'Dispose', so that if the object was disposed, it wouldn't be "re-disposed".
It is also usually advisable to hold a flag indicating whether the object has already been disposed or not. The follwoing pattern is usually pretty good:
class MyDisposable: IDisposable {
public void Dispose() {
lock(this) {
if (disposed) {
return;
}
disposed = true;
}
GC.SuppressFinalize(this);
// Do actual disposing here ...
}
private bool disposed = false;
}
Of course, locking is not always necessary, but if you're not sure if your class would be used in a multi-threaded environment or not, it is advisable to keep it.
Unfortunately there isn't any way to do this directly in the code. If this is an issue in house, there are various code analysis solutions that could catch these sort of problems. Have you looked into FxCop? I think that this will catch these situations and in all cases where IDisposable objects might be left hanging. If it is a component that people are using outside of your organization and you can't require FxCop, then documentation is really your only recourse :).
Edit: In the case of finalizers, this doesn't really guarantee when the finalization will happen. So this may be a solution for you but it depends on the situation.
#Quarrelsome
If will get called when the object is moved out of scope and is tidied by the garbage collector.
This statement is misleading and how I read it incorrect: There is absolutely no guarantee when the finalizer will be called. You are absolutely correct that billpg should implement a finalizer; however it will not be called automaticly when the object goes out of scope like he wants. Evidence, the first bullet point under Finalize operations have the following limitations.
In fact Microsoft gave a grant to Chris Sells to create an implementation of .NET that used reference counting instead of garbage collection Link. As it turned out there was a considerable performance hit.
~ClassName()
{
}
EDIT (bold):
If will get called when the object is moved out of scope and is tidied by the garbage collector however this is not deterministic and is not guaranteed to happen at any particular time.
This is called a Finalizer. All objects with a finaliser get put on a special finalise queue by the garbage collector where the finalise method is invoked on them (so it's technically a performance hit to declare empty finalisers).
The "accepted" dispose pattern as per the Framework Guidelines is as follows with unmanaged resources:
public class DisposableFinalisableClass : IDisposable
{
~DisposableFinalisableClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// tidy managed resources
}
// tidy unmanaged resources
}
}
So the above means that if someone calls Dispose the unmanaged resources are tidied. However in the case of someone forgetting to call Dispose or an exception preventing Dispose from being called the unmanaged resources will still be tidied away, only slightly later on when the GC gets its grubby mitts on it (which includes the application closing down or unexpectedly ending).
The best practice is to use a finaliser in your class and always use using blocks.
There isn't really a direct equivalent though, finalisers look like C destructors, but behave differently.
You're supposed to nest using blocks, that's why the C# code layout defaults to putting them on the same line...
using (SqlConnection con = new SqlConnection("DB con str") )
using (SqlCommand com = new SqlCommand( con, "sql query") )
{
//now code is indented one level
//technically we're nested twice
}
When you're not using using you can just do what it does under the hood anyway:
PleaseDisposeMe a;
try
{
a = new PleaseDisposeMe();
throw new Exception();
}
catch (Exception ex) { Log(ex); }
finally {
//this always executes, even with the exception
a.Dispose();
}
With managed code C# is very very good at looking after its own memory, even when stuff is poorly disposed. If you're dealing with unmanaged resources a lot it's not so strong.
This is no different from a programmer forgetting to use delete in C++, except that at least here the garbage collector will still eventually catch up with it.
And you never need to use IDisposable if the only resource you're worried about is memory. The framework will handle that on it's own. IDisposable is only for unmanaged resources like database connections, filestreams, sockets, and the like.
A better design is to make this class release the expensive resource on its own, before its disposed.
For example, If its a database connection, only connect when needed and release immediately, long before the actual class gets disposed.