I don't quite understand the workings of using/Disposable objects - c#

I asked a question regarding returning a Disposable (IDisposable) object from a function, but I thought that I would muddle the discussion if I raised this question there.
I created some sample code:
class UsingTest
{
public class Disposable : IDisposable
{
public void Dispose()
{
var i = 0;
i++;
}
}
public static Disposable GetDisposable(bool error)
{
var obj = new Disposable();
if (error)
throw new Exception("Error!");
return obj;
}
}
I coded it this way deliberately, because then I call:
using (var tmp = UsingTest.GetDisposable(true)) { }
Using the debugger, I notice that the Dispose method never executes, even though we've already instantiated a Disposable object. If I correctly understand the purpose of Dispose, if this class actually had opened handles and the like, then we would not close them as soon as we had finished with them.
I ask this question because this behavior aligns with what I would expect, but in the answers to the related question, people seemed to indicate that using would take care of everything.
If using still somehow takes care of all of this, could someone explain what I'm missing? But, if this code could indeed cause resource leak, how would you suggest I code GetDisposable (with the condition that I must instantiate the IDisposable object and run code which could throw an exception prior to the return statement)?

The reason it's never called is because of the way you allocate it. The "tmp" variable is never allocated at all, because the GetDisposable(bool) function never returns due to the fact that you threw an exception.
If you were to say instead the following,
using (var tmp = new Disposable())
{
throw new ArgumentException("Blah");
}
then you would see that IDisposable::Dispose() does indeed get called.
The fundamental thing to understand is that the using block has to get a valid reference to the IDisposable object. If some exception occurs so that the variable declared in the using block does not get assigned then you are out of luck, because the using block will have no knowledge of the IDisposable object.
As for returning an IDisposable object from a function, you should use a standard catch block inside of the function to call Dispose() in the event of a failure, but obviously you should not use a using block because this will dispose the object before you are ready to do so yourself.

Depending upon what semantics you want for GetDisposable, this is probably how I would implement it:
public static Disposable GetDisposable(bool error)
{
var obj = new Disposable();
try
{
if (error)
throw new Exception("Error!");
return obj;
}
catch (Exception)
{
obj.Dispose();
throw;
}
}

This is because the tmp variable is never assigned. It's something you need to be careful of with disposable objects. A better definition for GewtDisposable would be:
public static Disposable GetDisposable(bool error)
{
var obj = new Disposable();
try
{
if (error)
throw new Exception("Error!");
return obj;
}
catch
{
obj.Dispose();
throw;
}
}
Because it ensures that obj is disposed.

The IDisposable interface simply guarantees that the class that implements it has a Dispose method. It does nothing in regard to calling this method. A using block will call Dispose on the object when the block is exited.

You create an IDisposable in GetDisposable but since you exit the function by throwing an exception, it never gets returned and hence tmp never gets assigned. The using statement is shorthand for
var tmp = UsingTest.GetDisposable(true);
try { }
finally
{
if(tmp != null) tmp.Dispose();
}
and you never reach the try block. The solution in your example is to check the error flag before creating the disposable obj:
public static Disposable GetDisposable(bool error)
{
if (error)
throw new Exception("Error!");
return new Disposable();
}

A related question is Handling iDisposable in failed initializer or constructor and I think the answer is that if you want to avoid leaking disposable objects from a failed constructor, you'll have to smuggle out a copy of the object from the constructor (e.g. stash it in a passed-in container, or assign it to a passed-by-reference variable) and wrap the constructor call in a catch block. Icky, but I don't know how to do it better. VB.net can actually manage a little better than C# because of how its initializers work.

Related

When using "DbConnection" should I use "using" or try-catch-finally to use DbConnection.close() to close the connection?

I was searching the web for a while now. But didn't find any clear answer to my question. Whether when connecting to a database I should use "using" or I can just go with try-catch-finally? What I mean is:
I don't know if I should call the dispose method each time I finish interacting with the database or just close the connection.
static public List<Category> GetAll()
{
List<Category> CategoryList;
try
{
BaseDAO.Dbconn.Open();
BaseDAO.SetCommand(BaseDAO.CommandAction.Read, "SELECT * FROM Categories");
CategoryList = new List<Category>();
using (DbDataReader reader = BaseDAO.Dbcmd.ExecuteReader())
{
while (reader.Read())
{
int ID = reader.GetInt32(reader.GetOrdinal("CategoryID"));
string Name = reader.GetString(reader.GetOrdinal("CategoryName"));
string Description = reader.GetString(reader.GetOrdinal("Description"));
CategoryList.Add(new Category(ID, Name, Description));
}
}
return CategoryList;
}
catch (Exception ex)
{
BaseDAO.Dbconn.Dispose();
throw ex;
}
finally { BaseDAO.Dbconn.Close(); }
}
The "Dbconnection" is static not sure if this is a good solution as well...
I am getting to know ADO and just wanted to know what's the best answer for this kind of question.
It doesn't make any difference - whatever you prefer. The using clause gets turned into a try-finally by the compiler anyway.
EDIT I just noticed you are only calling Dispose if an exception occurs. You should move this into the finally clause as well. Dispose will call Close, so you don't need to specifically call it if you don't want to.
Further edit Given that, as you say, your DbConnection is static, then you don't want to call Dispose, but you do need to call Close. However, there should not be any need to use a static DbConnection - connection pooling will take care of efficiently handling the connections. Your code should create a new connection instance every time.
Reference: Using Statement C#.
The using statement allows the programmer to specify when objects that use resources should release them.
The object provided to the using statement must implement the
IDisposable interface. This interface provides the Dispose method,
which should release the object's resources.
A using statement can be exited either when the end of the using statement is reached or if an exception is thrown and control leaves the statement block before the end of the statement.
Reference : Example
As per Code Project, the .NET CLR converts
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
to:
{
// limits scope of myRes
MyResource myRes= new MyResource();
try
{
myRes.DoSomething();
}
finally
{
// Check for a null resource.
if (myRes!= null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
Calling Dispose is equivalent to calling Close in most (if not all) DbConnection implementations, so there's no need to call the former if you are already calling the latter. Just make sure you do so in a finally in case there's an exception.

Do I have to worry about garbage collection in this c# EF scenario?

try
{
using (MapDataContainer ent = new MapDataContainer()) //is an autogen'd EF object
{
//do some stuff, assume it throws an error
}
}
catch(Exception ex) //catching outside using not sure if IDispose called
{
//handle error
}
Normally I understand that the using called the IDispose on the EF object. So supposing it threw an exception... Is this a possible memory leak scenario?
You're fine. "using" is actually a try..finally in disguise.
The using statement is actually
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
So as you can see, the Dispose is always called. The only exception is if it is a CLR error, but in that case you're out of luck anyway.
As MSDN says, using statement is translated by C# compiler to try-finally block to ensure, that IDisposable.Dispose() is called:
{
MapDataContainer ent = new MapDataContainer();
try
{
...
}
finally
{
if (ent != null)
((IDisposable)ent).Dispose();
}
}
The only cases when IDisposable.Dispose() is not called is when Environment.FailFast is called inside using statement block or when exception is thrown inside or right after the constructor of MapDataContainer(), but this still doesn't prevent Garbage collector to collect this object. Additionally objects that implements IDisposable typically (but not necessarily) call IDisposable.Dispose() in destructor to ensure that any unmanaged resources will be correctly released even in programmer forgets to call it manually or wrap it in using statement.

C# - Lock question using EnterWriteLock

The following code is from MSDN:
private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
private Dictionary<int, string> innerCache = new Dictionary<int, string>();
public void Add(int key, string value)
{
cacheLock.EnterWriteLock();
try
{
innerCache.Add(key, value);
}
finally
{
cacheLock.ExitWriteLock();
}
}
I've seen code like this in other places.The EnterWriteLock() is always outside the try block. Does anyone know why it's not inside the try block?
Suppose the EnterWriteLock() fails. For whatever reason.
Then the one thing you shouldn't do is to Exit a lock you never Entered.
It's a very basic pattern that also holds for example for streams, but not seen as often thanks to the using() {} statement.
var s = File.Create(...);
// (only) if the previous line succeeded,
// we gain the responsibility to close s, no matter what
try
{
// do some I/O
}
finally
{
s.Dispose();
}
Because that would be a bug. You can't call ExitWriteLock until you're sure that you entered it. Imagine what happens if you moved it inside try {} and EnterWriteLock() throws an exception. That's a double kaboom. Kabloom, screws up the exception message.
If EnterWriteLock throws an exception, there is no need to call ExitWriteLock, hence the reason it is not in the try block. ExitWriteLock should always be called if EnterWriteLock is successfully invoked. You may want to wrap a try block around EnterWriteLock in certain scenarios as it can throw a LockRecursionException. ExitWriteLock can also throw a SynchronizationLockException and may require a try block in your application.

Catching exceptions thrown in the constructor of the target object of a Using block

using(SomeClass x = new SomeClass("c:/temp/test.txt"))
{
...
}
Inside the using block, all is fine with treating exceptions as normal. But what if the constructor of SomeClass can throw an exception?
Put your using into the try catch f.e.
try
{
using(SomeClass x = new SomeClass("c:/temp/test.txt"))
{
...
}
}
catch(Exception ex)
{
...
}
Yes, this will be a problem when the constructor throws an exception. All you can do is wrap the using block within a try/catch block. Here's why you must do it that way.
using blocks are just syntactic sugar and compiler replaces each using block with equivalent try/finall block. The only issue is that the compiler does not wrap the constructor within the try block. Your code after compilation would have following conversion in the IL.
//Declare object x of type SomeClass.
SomeClass x;
//Instantiate the object by calling the constructor.
x = new SomeClass("c:/temp/test.txt");
try
{
//Do some work on x.
}
finally
{
if(x != null)
x.Dispose();
}
As you can see from the code, the object x will not be instantiated in case when the constructor throws an exception and the control will not move further from the point of exception raise if not handled.
I have just posted a blog-post on my blog on this subject last night.
I'm just now wondering why C#
designers did not wrap object
construction within the try block
which according to me should have been
done.
EDIT
I think I found the answer why C# does not wrap object construction into try block generated in place of the using block.
The reason is simple. If you wrap both declaration and instantiation within the try block then the object would be out of scope for the proceeding finally block and the code will not compile at because, for finally block the object hardly exists. If you only wrap the construction in the try block and keep declaration before the try block, even in that case the it will not compile since it finds you're trying to use an assigned variable.
I threw a quick test program together to check this, and it seems that the Dispose method does not get called when an exception is thrown in the constructor;
class Program
{
static void Main(string[] args)
{
try
{
using (OtherClass inner = new OtherClass())
{
Console.WriteLine("Everything is fine");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.Read();
}
}
class OtherClass : IDisposable
{
public OtherClass()
{
throw new Exception("Some Error!");
}
void IDisposable.Dispose()
{
Console.WriteLine("I've disposed my resources");
}
}
Output :
Some Error!
If you don't throw the exception..
Output :
Everything is fine
I've disposed my resources
Presumably this is because the object was never created, so there's nothing to call Dispose on.
I'm not sure what would happen if the constructor had already allocated some resources which would normally require a proper clean up through Dispose and the exception occurred afterwards though.
This should not be a problem with a well-designed class. Remember the overall question:
public class HoldsResources : IDisposable
{
public HoldsResources()
{
// Maybe grab some resources here
throw new Exception("whoops");
}
}
using (HoldsResources hr = new HoldsResources())
{
}
So, the question is, what should you do about the resources allocated by the HoldsResources constructor before it threw an exception?
The answer is, you shouldn't do anything about those resources. That's not your job. When it was decided that HoldsResources would hold resources, that brought the obligation to properly dispose of them. That means a try/catch/finally block in the constructor, and it means proper implementation of IDisposable to dispose of those resources in the Dispose method.
Your responsibility is to use the using block to call his Dispose method when you're through using the instance. Nothing else.
When you get a hold of resources in the ctor that are not subject to garbage collection, you have to make sure to dispose of them when things go south.
This sample shows a ctor which will prevent a leak when something goes wrong, the same rules apply when you allocate disposables inside a factory method.
class Sample
{
IDisposable DisposableField;
...
public Sample()
{
var disposable = new SomeDisposableClass();
try
{
DoSomething(disposable);
DisposableField = disposable;
}
catch
{
// you have to dispose of it yourself, because
// the exception will prevent your method/ctor from returning to the caller.
disposable.Dispose();
throw;
}
}
}
Edit: I had to change my sample from a factory to a ctor, because apparantly it wasn't as easy to understand as I hoped it would be. (Judging from the comments.)
And of course the reason for this is: When you call a factory or a ctor, you can only dispose of its result. When the call goes through, you have to assume that everything's okay so far.
When calling a ctor or factory you don't have to do any reverse-psychoanalysis to dispose of anything you can't get hold of anyways. If it does throw an exception, it is in the factories/ctor's responsibility to clear anything half-allocated before re-throwing the exception.
(Hope, this time, it was elaborate enough...)

Can a scope block with the "using" keyword react to exceptions?

I have the need to do some logging within my code. I'm required to use an internal company-developed library to record some information. Here's how it works.
Recorder recorder = Recorder.StartTiming();
DoSomeWork();
recorder.Stop(); // Writes some diagnostic information.
To ensure that Stop() is always called, I created a wrapper class that allows a clean "using" block.
using (RecorderWrapper recorderWrapper = new RecorderWrapper) // Automatically calls Recorder.StartTiming() under the covers
{
DoSomeWork();
} // When the recorderWrapper goes out of scope, the 'using' statement calls recorderWrapper.Dispose() automatically - which calls recorder.Stop() under the covers
it's worked well so far. However, there's a change my company is requiring, that would look something like this on the original code:
Recorder recorder = Recorder.StartTiming();
try
{
DoSomeWork();
}
catch (Exception ex)
{
recorder.ReportFailure(ex); // Write out some exception details associated with this "transaction"
}
recorder.Stop(); // Writes some diagnostic information.
I'd like to avoid try/catches in all my 'using' scope blocks with RecorderWrapper. Is there a way I can accomodate the "ReportFailure()" call and still leverage the 'using' scope block?
Specifically, I want everyone on my team to "fall into a pit of success", i.e. make it easy to do the right thing. To me, this means making it really hard to forget to call recorder.Stop() or forget the try/catch.
Thanks!
You might be able to create a method on the recorder to hide this:
public void Record(Action act)
{
try
{
this.StartTiming();
act();
}
catch(Exception ex)
{
this.ReportFailure(ex);
}
finally
{
this.Stop();
}
}
So your example would then just be:
recorder.Record(DoSomeWork);
You could always try something like:
Edit by 280Z28: I'm using a static StartNew() method here similar to Stopwatch.StartNew(). Make your Recorder class IDisposable, and call Stop() from Dispose(). I don't think it gets any more clear than this.
using (Recorder recorder = Recorder.StartNew())
{
try
{
DoSomeWork();
}
catch (Exception ex)
{
recorder.ReportFailure(ex);
}
}
You could continue to use the RecorderWrapper you have, but add a TryExecuting method that accepts a lambda of what you want to happen add runs it in a try/catch block. eg:
using (RecorderWrapper recorderWrapper = new RecorderWrapper) // Automatically calls Recorder.StartTiming() under the covers
{
recorderWrapper.TryExecuting(() => DoSomeWork());
}
Inside RecorderWrapper:
public void TryExecuting(Action work)
{
try { work(); }
catch(Exception ex) { this.ReportFailure(ex); }
}
You could copy the pattern used by TransactionScope, and write a wrapper that must be actively completed - if you don't call Complete(), then the Dispose() method (which gets called either way) assumes an exception and does your handling code:
using(Recorder recorder = Recorder.StartTiming()) {
DoSomeWork();
recorder.Complete();
}
Personally, though, I'd stick with try/catch - it is clearer for maintainers in the future - and it provides access to the Exception.
No, a using block is only syntactic sugar for a try/finally block. It doesn't deal with try/catch. At that point you're going to be left with handling it yourself since it looks like you need the exception for logging purposes.
A using block is effectively a try/finally block that calls dispose on the object in question.
So, this:
using(a = new A())
{
a.Act();
}
is (i think, exactly) equivalent to this:
a = new A();
try
{
a.Act();
}
finally
{
a.Dispose();
}
And you can tack your catches onto the end of the try block.
Edit:
As an alternative to Rob's solution:
Recorder recorder = Recorder.StartNew()
try
{
DoSomeWork();
}
catch (Exception ex)
{
recorder.ReportFailure(ex);
}
finally
{
recorder.Dispose();
}
Oops, I hadn't noticed that a new instance of Recorder was being created by StartTiming. I've updated the code to account for this. The Wrap function now no longer takes a Recorder parameter but instead passes the recorder it creates as an argument to the action delegate passed in by the caller so that the caller can make use of it if needed.
Hmmm, I've needed to do something very similar to this pattern, lambdas, the Action delegate and closures make it easy:
First define a class to do the wrapping:
public static class RecorderScope
{
public static void Wrap(Action<Recorder> action)
{
Recorder recorder = Recorder.StartTiming();
try
{
action(recorder);
}
catch(Exception exception)
{
recorder.ReportFailure(exception);
}
finally
{
recorder.Stop();
}
}
}
Now, use like so:
RecorderScope.Wrap(
(recorder) =>
{
// note, the recorder is passed in here so you can use it if needed -
// if you never need it you can remove it from the Wrap function.
DoSomeWork();
});
One question though - is it really desired that the catch handler swallows the exception without rethrowing it? This would usually be a bad practice.
BTW, I'll throw in an addition to this pattern which can be useful. Although, it doesn't sound like it applies to what you're doing in this instance: Ever wanted to do something like the above where you want to wrap some code with a set of startup actions and completion actions but you also need to be able to code some specific exception handling code. Well, if you change the Wrap function to also take an Action delegate and constrain T to Exception, then you've got a wrapper which allows user to specify the exception type to catch, and the code to execute to handle it, e.g.:
public static class RecorderScope
{
public static void Wrap(Action<Recorder> action,
Action<Recorder, T1> exHandler1)
where T1: Exception
{
Recorder recorder = Recorder.StartTiming();
try
{
action(recorder);
}
catch(T1 ex1)
{
exHandler1(recorder, ex1);
}
finally
{
recorder.Stop();
}
}
}
To use.. (Note you have to specify the type of exception, as it obviously cannot be inferred. Which is what you want):
RecorderScope.Wrap(
(recorder) =>
{
DoSomeWork();
},
(recorder, MyException ex) =>
{
recorder.ReportFailure(exception);
});
You can then extend this pattern by providing multiple overloads of the Wrap function which take more than one exception handler delegate. Usually five overloads will be sufficient - it's pretty unusual for you to need to catch more than five different types of exceptions at once.
Don't add another level of indirection. If you need to catch the Exception, use try..catch..finally and call Dispose() in the finally block.

Categories