Using statement and try-catch()-finally repetition? - c#

The using(...) statement is syntactic sugar for try{} finally {}.
But if I then have a using statement like below:
using (FileStream fs = File.Open(path))
{
}
Now I want to catch the exceptions that opening this file could cause (and this is fairly high risk code in that it can fail due to the environment), but if I write try-catch inside would that not be repetition? When the code gets compiled to IL, I assume the repetition will get deleted when the code is JITted?
However, I would want to catch the exceptions opening a file can cause (so I should wrap the try-catch outside the using statement's scope), and also the exceptions for whatever I do inside the using block so I should add the try-catch inside the block.
This seems like I am adding a lot of repetition to what the CLR probably does inside. Does the CLR add catch clauses?
My colleague argued that a using statement is messy (but this was because a single line was slightly long due to me hard coding them as I needed to change them very quickly and didn't have access to other parts of the code base). Said colleague doesn't use the using statement but is there ever any functional difference between the using statement and try-finally/try-catch-finally? I did see one case of this where WCF services have a not well known corner case about using finally and returning values (something about finally). The solution was to use a check block. Is there anything like this in C#?
On another note, are all types which implement IDisposale owners of unmanaged resources? A discussion with my friend pointed the answer to being no. (I have also read some threads in the using section of this forum, some very good knowledge there).

You can implement the pattern yourself if you need to handle some exceptions if you really want to. Personally, I still find it simpler (and more importantly, clearer) to just wrap the using in try/catch block.
But if you do it yourself, make sure you get it right. The Using block also creates an anonymous scope block so that your variable becomes eligible for collection sooner. The .Dispose() method that's called at the end of the Using block only cleans up unmanaged resources, and so any memory your object holds may hang around a little longer. It's not likely a huge concern, but it is worth remembering just in case.
So, to do a direct adaption of the pattern, your code needs to look more like this:
{
FileStream fs;
try
{
fs = File.Open(path);
}
catch (FileNotFoundException e) { /* ... */ }
catch (IOException e) { /* ... */ }
catch (Exception e) {/* ... */}
finally
{
if (fs != null) fs.Dispose();
}
}
Personally, I'd like to see Using expanded to support Catch and Finally blocks. Since they're already performing a transformation on the code, it doesn't seem like this would add that much additional complexity.

My preference would be to keep the using statement and wrap it in a try/catch. The outer try/catch will catch whatever exceptions you need to watch for, while ignoring the Dispose(). This has the added advantage of protecting you from yourself should you refactor this later to move the try/catch elsewhere (like in a calling function).
As far as your question about IDisposable: Anyone can implement this for any reason they like. There is no technical reason for it to be limited to unmanaged resources. (Whether or not it should be limited to unmanaged resources in your code is a different question).

The biggest difference between using and try-finally is that using will only call the Dispose() method. If you implement your own finally block can do other logic, for example logging, which would not be included in the using.

If you need to explicitly handle different exceptional cases which may happen during the statement, you could replace using with try/catch/finally and call Dispose() explicitly in the finally. Or you could put a try/catch around the using block to separate exceptional circumstances from ensuring disposal.
The only thing using does is ensure Dispose() is called even if an exception is thrown inside the block. That is a very limited, highly specific implementation of the general try/[catch]/finally structure.
The important thing is that none of these options have any real impact - as long as it does what you need, is readable and understandable, who cares? It's not like an extra try will be a bottleneck or anything!
To answer your last question - no, IDisposable definitely does not necessarily mean the implementer has handles to unmanaged resources. It's a far simpler and more generic pattern than that. Here's one useful example:
public class Timer : IDisposable
{
internal Stopwatch _stopwatch;
public Timer()
{
this._stopwatch = new Stopwatch();
this._stopwatch.Start();
}
public void Dispose()
{
this._stopwatch.Stop();
}
}
We can use this to time things without having to explicitly rely on start and stop being called by using:
using(Timer timer = new Timer())
{
//do stuff
}

The using construct is shorthand for a try/finally block. That is, the compiler generates:
FileStream fs = null;
try
{
fs = File.Open(path);
// ...
}
finally
{
if (fs != null)
fs.Dispose();
}
So it is proper to use using if you do not need a catch, but if you do then you should just use a normal try/catch/finally.

Related

Is using try/finally a good practice for memory management?

One of my senior told me to use try/ finally block for all the methods to clear the initialized objects data.
for eg:
var serviceProxy = new NotificationServiceProxy();
try
{
return serviceProxy.GetNotifications(userID, request.Filters, request.FilterProperty, usertypeid);
}
finally
{
serviceProxy = null;
}
Is that a good practice? if i'm using try/ catch for all my methods to clear the initialized objects data.
Not in C#, use using instead:
using(var serviceProxy = new NotificationServiceProxy()){
serviceProxy.GetNotifications(userID, request.Filters, request.FilterProperty, usertypeid);
// Do stuff with the service proxy
}
// serviceProxy has now been cleaned up
This is the pattern to ensure that IDisposable variable get cleaned up.
For instances that aren't disposable this isn't needed - just let them pass out of scope and leave it to the GC.
If NotificationServiceProxy uses lots of resources and you need to be sure that it is finalised correctly then make it disposable and always wrap it in a using or in another class that also implements IDisposable. If it doesn't then this try-finally pattern is a waste of time.
No that's not a good practice.
You are doing work manually, the compiler/garbage collector will do for you. This is unnecessary time spent and unnecessary code clutter you need to remove or maintain later.
You completely missed to .Dispose() the service reference. Although this could be done in a finally block, the using block exists exactly for this purpose.
You don't need to clear a local variable. Before you exit the method, the stack will be reverted anyway (which will free up the space on the stack used by the variable) and setting the local variable to null will not free up space on the heap (the garbage collector will do that). Use try finally if you need to do some cleanup, for example object disposal or closing files.
Is it a good practice or not, it depends on the scenarios. It's often good to catch the exception so that you can handle unexpected cases gracefully. If your program has developed some other ways to handle exception cases then Try/Finally block should be suffice since Catch block have some performance penalties.
Please review the Consideration When Using Try Catch article from MSDN.
First of all, you have no need to clear the local variables (Garbage Collector will do it for you), however, it's safe:
Object o = new Object();
...
o = null; // safe, but not required
What you have to do is to clear unmanaged resources; typical way for this is implementing IDisposable interface and wrapping corresponding instances into using:
// Providing that serviceProxy implements IDisposable
using (var serviceProxy = new NotificationServiceProxy()) {
return serviceProxy.GetNotifications(
userID,
request.Filters,
request.FilterProperty,
usertypeid);
} // <- here .Net will call serviceProxy.Dispose() and free the resources allocated
sometime you have to restore the initial state, and that is the case try..finally has been designed for:
Cursor savedCursor = Cursor.Current;
try {
Cursor.Current = Cursors.WaitCursor;
...
}
finally {
// Rain (exception thrown) or shine (no exception), please, restore my cursor
Cursor.Current = savedCursor;
}
In your particular case, I can't see any state to restore, that's why try..finally is not the pattern that should be used. However, it's quite possible that serviceProxy allocates some unmanaged resources (say, TCP/IP port, connection or alike) so it seems that you should implement IDisposable for NotificationServiceProxy class (if it's not imlemented yet) and wrap the instance into using.
This makes sense when you need something that HAS to happen like Disposing IDisposable objects whether your operation has failed or succeeded.
try
{
myDisposable.Do();
}
finally
{
myDisposable.Dispose();
}
you have a built in mechanism which does exactly that : Using
using(IDisposable myDisposable = new Something())
{
myDisposable.Do();
}
Now has to good practice :
That's kinda up to your error handling strategy and cleanup needs :
If i have something that HAS to be done whether the operation succeed or failed i would put a try finally block.
if i have something that only need error handling and no cleanup i would place try catch without a finally block
If i have to do some kind of error handling i would also place a catch block in there
If i wan't to make some error handling there like a log and then have the Exception propagate from that stack i would also re throw the exception.
or any permutation of the above conditions ..
For instance :
try
{
myDisposable.Do();
}
catch(Exception e)
{
Log("Error at something something",e);
throw e;
}
finally
{
myDisposable.Dispose();
}
I for one do not place try catch finally every where, i want the places in my code that which do contain them stand out stating that these are operations that are known to go wrong for some known reason.
i would welcome new exceptions i'm not yet aware of and handle them accordingly.
Yes, if you need to dispose a variables.

Take 2: Is it abusive to use IDisposable and “using” as a means for getting “scoped behavior”?

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

Isn't it redundant to dispose of an object inside its own using block?

While programming over an existent class, I've noticed that someone has written something like this:
using(DisposableObject disp = new DisposableObject())
{
...
...
disp.Dispose()
}
And then I wonder: isn't the using block enough to dispose an object? Could be there any way Dispose() can be useful in such case?
Cause it doesn't make any sense to me...
In your case it is useless to use dispose inside using because when using statement's scope ends it automatically calls dispose. That's why you can only write objects which implements IDisposable Interface inside using brackets.
using(.......)
Moreover if there was any statement using disp object after disp.Dispose() it would give an error, because by then object would have been disposed, i.e. its memory has been released.
But beware
If dispose is last line before using scope ends then it is useless.
But it is not useless when there are more lines after dispose.
Yes, a using block is actually equivalent to and an alternative syntax for:
var d = new DisposableObject();
try
{
d.DoSomething();
}
finally
{
if(d != null)
((IDisposable)d).Dispose();
}
Note that it uses finally instead of something like 'catch'. The finally-clause will always be executed, even if there's an exception.
using is enough. There is no reason to call Dispose twice.
There are two reasons why you can use Dispose inside a using block:
you want to dispose the object before the using block ends. In this case the using block is a "safety net" that ensures you that your object will be disposed even if an exception happens. (using behaves like a try block which has a finally block in which your object is disposed)
calling Dispose makes more clear what you're doing. This is typical, i.e. of
transaction scopes:
using(TransactionScope ts=new TransactionScope)
{
...
if (cond)
{
ts.Complete();
}
else
{
ts.Dispose(); // makes it clear you're rolling back the transaction
}
}
This call to Dispose it's not neccesary, but it's "explanatory". It makes more obvous that the transaction is rolled back.
#Nikhil Agrawal is right. One thing I need mention is when you implement Idisposable interface, you should make sure it can be invoked many times. That's mean you should do some validation.

Occasions when the using statement and IDisposable should never be used

I was reading about this scenario where making use of the C# using statement can cause problems. Exceptions thrown within the scope of the using block can be lost if the Dispose function called at the end of the using statement was to throw an exception also. This highlights that care should be taken in certain cases when deciding whether to add the using statement.
I only tend to make use of using statements when using streams and the classes derived from DbConnection. If I need to clean up unmanaged resources, I would normally prefer to use a finally block.
This is another use of the IDisposable interface to create a performance timer that will stop the timer and log the time to the registry within the Dispose function.
http://thebuildingcoder.typepad.com/blog/2010/03/performance-profiling.html
Is this good use of the IDisposable interface? It is not cleaning up resources or disposing of any further objects. However, I can see how it could clean up the calling code by wrapping the code it is profiling neatly in a using statement.
Are there times when the using statement and the IDisposable interface should never be used? Has implementing IDisposable or wrapping code in a using statement caused problems for you before?
Thanks
I would say, always use using unless the documentation tells you not to (as in your example).
Having a Dispose method throw exceptions rather defeats the point of using it (pun intended). Whenever I implement it, I always try to ensure that no exceptions will be thrown out of it regardless of what state the object is in.
PS: Here's a simple utility method to compensate for WCF's behaviour. This ensures that Abort is called in every execution path other than when Close is called, and that errors are propogated up to the caller.
public static void CallSafely<T>(ChannelFactory<T> factory, Action<T> action) where T : class {
var client = (IClientChannel) factory.CreateChannel();
bool success = false;
try {
action((T) client);
client.Close();
success = true;
} finally {
if(!success) {
client.Abort();
}
}
}
If you find any other funny behaviour cases elsewhere in the framework, you can come up with a similar strategy for handling them.
The general rule of thumb is simple: when a class implements IDisposable, use using. When you need to catch errors, use try/catch/finally, to be able to catch the errors.
A few observations, however.
You ask whether situations exist where IDisposable should not be used. Well: in most situations you shouldn't need to implement it. Use it when you want to free up resources timely, as opposed to waiting until the finalizer kicks in.
When IDisposable is implemented, it should mean that the corresponding Dispose method clears its own resources and loops through any referenced or owned objects and calls Dispose on them. It should also flag whether Dispose is called already, to prevent multiple cleanups or referenced objects to do the same, resulting in an endless loop. However, all this is no guarantee that all references to the current object are gone, which means it will remain in memory until all references are gone and the finalizer kicks in.
Throwing exceptions in Dispose is frowned upon and when it happens, state is possibly not guaranteed anymore. A nasty situation to be in. You can fix it by using try/catch/finally and in the finally block, add another try/catch. But like I said: this gets ugly pretty quickly.
Using using is one thing, but don't confuse it with using try/finally. Both are equal, but the using-statement makes life easier by adding scoping and null-checks, which is a pain to do by hand each time. The using-statement translates to this (from C# standard):
{
SomeType withDispose = new SomeType();
try
{
// use withDispose
}
finally
{
if (withDispose != null)
{
((IDisposable)withDispose).Dispose();
}
}
}
There are occasions where wrapping an object into a using-block is not necessary. These occasions are rare. They happen when you find yourself inheriting from an interface that inherits from IDisposable just in case a child would require disposing. An often-used example is IComponent, which is used with every Control (Form, EditBox, UserControl, you name it). And I rarely see people wrapping all these controls in using-statements. Another famous example is IEnumerator<T>. When using its descendants, one rarely sees using-blocks either.
Conclusion
Use the using-statement ubiquitously, and be judicious about alternatives or leaving it out. Make sure you know the implications of (not) using it, and be aware of the equality of using and try/finally. Need to catch anything? Use try/catch/finally.
I think the bigger problem is throwing exceptions in Dispose. RAII patterns usually explicitly state that such should not be done, as it can create situations just like this one. I mean, what is the recovery path for something not disposing correctly, other than simply ending execution?
Also, it seems like this can be avoided with two try-catch statements:
try
{
using(...)
{
try
{
// Do stuff
}
catch(NonDisposeException e)
{
}
}
}
catch(DisposeException e)
{
}
The only problem that can occur here is if DisposeException is the same or a supertype of NonDisposeException, and you are trying to rethrow out of the NonDisposeException catch. In that case, the DisposeException block will catch it. So you might need some additional boolean marker to check for this.
The only case I know about is WCF clients. That's due to a design bug in WCF - Dispose should never throw exceptions. They missed that one.
One example is the IAsyncResult.AsyncWaitHandle property. The astute programmer will recognize that WaitHandle classes implement IDisposable and naturally try to greedily dispose them. Except that most of the implementations of the APM in the BCL actually do lazy initialization of the WaitHandle inside the property. Obviously the result is that the programmer did more work than was necessary.
So where is the breakdown? Well, Microsoft screwed up the IAsyncResult inteface. Had they followed their own advice IAsyncResult would have derived from IDisposable since the implication is that it holds disposable resources. The astute programmer would then just call Dispose on the IAsyncResult and let it decide how best to dispose its constituents.
This is one of the classic fringe cases where disposing of an IDisposable could be problematic. Jeffrey Richter actually uses this example to argue (incorrectly in my opinion) that calling Dispose is not mandatory. You can read the debate here.

How to do C++ style destructors in C#?

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.

Categories

Resources