Dealing with nested "using" statements in C# - c#

I've noticed that the level of nested using statements has lately increased in my code. The reason is probably because I use more and more of async/await pattern, which often adds at least one more using for CancellationTokenSource or CancellationTokenRegistration.
So, how to reduce the nesting of using, so the code doesn't look like Christmas tree? Similar questions have been asked on SO before, and I'd like to sum up what I've learnt from the answers.
Use adjacent using without indentation. A fake example:
using (var a = new FileStream())
using (var b = new MemoryStream())
using (var c = new CancellationTokenSource())
{
// ...
}
This may work, but often there's some code between using (e.g. it may be too early to create another object):
// ...
using (var a = new FileStream())
{
// ...
using (var b = new MemoryStream())
{
// ...
using (var c = new CancellationTokenSource())
{
// ...
}
}
}
Combine objects of the same type (or cast to IDisposable) into single using, e.g.:
// ...
FileStream a = null;
MemoryStream b = null;
CancellationTokenSource c = null;
// ...
using (IDisposable a1 = (a = new FileStream()),
b1 = (b = new MemoryStream()),
c1 = (c = new CancellationTokenSource()))
{
// ...
}
This has the same limitation as above, plus is more wordy and less readable, IMO.
Refactor the method into a few methods.
This is a preferred way, as far as I understand. Yet, I'm curious, why would the following be considered a bad practice?
public class DisposableList : List<IDisposable>, IDisposable
{
public void Dispose()
{
base.ForEach((a) => a.Dispose());
base.Clear();
}
}
// ...
using (var disposables = new DisposableList())
{
var a = new FileStream();
disposables.Add(a);
// ...
var b = new MemoryStream();
disposables.Add(b);
// ...
var c = new CancellationTokenSource();
disposables.Add(c);
// ...
}
[UPDATE] There are quite a few valid points in the comments that nesting using statements makes sure Dispose will get called on each object, even if some inner Dispose calls throw. However, there is a somewhat obscure issue: all nested exceptions possibly thrown by disposing of nested 'using' frames will be lost, besides the most outer one. More on this here.

In a single method, the first option would be my choice. However in some circumstances the DisposableList is useful. Particularly, if you have many disposable fields that all need to be disposed of (in which case you cannot use using). The implementation given is good start but it has a few problems (pointed out in comments by Alexei):
Requires you to remember to add the item to the list. (Although you could also say you have to remember to use using.)
Aborts the disposal process if one of the dispose methods throws, leaving the remaining items un-disposed.
Let's fix those problems:
public class DisposableList : List<IDisposable>, IDisposable
{
public void Dispose()
{
if (this.Count > 0)
{
List<Exception> exceptions = new List<Exception>();
foreach(var disposable in this)
{
try
{
disposable.Dispose();
}
catch (Exception e)
{
exceptions.Add(e);
}
}
base.Clear();
if (exceptions.Count > 0)
throw new AggregateException(exceptions);
}
}
public T Add<T>(Func<T> factory) where T : IDisposable
{
var item = factory();
base.Add(item);
return item;
}
}
Now we catch any exceptions from the Dispose calls and will throw a new AggregateException after going through all the items. I've added a helper Add method that allows a simpler usage:
using (var disposables = new DisposableList())
{
var file = disposables.Add(() => File.Create("test"));
// ...
var memory = disposables.Add(() => new MemoryStream());
// ...
var cts = disposables.Add(() => new CancellationTokenSource());
// ...
}

You should always refer to your fake example. When this is not possible, like you mentioned, then it is very likely that you can refactor the inner content into a separate method. If this also does not make sense you should just stick to your second example. Everything else just seems like less readable, less obvious and also less common code.

I would stick to the using blocks. Why?
It clearly shows your intentions with these objects
You don't have to mess around with try-finally blocks. It's error prone and your code gets less readable.
You can refactor embedded using statements later (extract them to methods)
You don't confuse your fellow programmers including a new layer of abstractions by creating your own logic

Your last suggestion hides the fact that a, b and c should be disposed explicitly. That`s why it's ugly.
As mentioned in my comment, if you'd use clean code principles you wouldn't run into these problems (usually).

Another option is to simply use a try-finally block. This might seem a bit verbose, but it does cut down unnecessary nesting.
FileStream a = null;
MemoryStream b = null;
CancellationTokenSource c = null;
try
{
a = new FileStream();
// ...
b = new MemoryStream();
// ...
c = new CancellationTokenSource();
}
finally
{
if (a != null) a.Dispose();
if (b != null) b.Dispose();
if (c != null) c.Dispose();
}

Related

Understanding how using block dispose of objects

I have the following code, where I want to immediately dispose of ApplicationDbContext instance:
using (var context = ApplicationDbContext.Create())
{
MyRepository myRespository = new MyRepository(context);
myRepository.ReadData();
}
If C# garbage collector wants to immediately dispose of ApplicationDbContext, it would have to immediately dispose of MyRepository as well, because it has a reference to ApplicationDbContext? Is this actually happening?
Or do I need to write my code like below to ensure ApplicationDbContext is Disposed, immediately?
using (var context = ApplicationDbContext.Create())
using (MyRepository myRespository = new MyRepository(context))
{
myRepository.ReadData();
}
Your second block of code is right.
One using clause is applied to one declaration.
Wat you wrote here:
using (var context = ApplicationDbContext.Create())
using (MyRepository myRespository = new MyRepository(context))
{
myRepository.ReadData();
}
Is the same as:
var context = ApplicationDbContext.Create();
try
{
var myRespository = new MyRepository(context);
try
{
myRepository.ReadData();
}
finally
{
myRepository.Dispose();
}
}
finally
{
context.Dispose();
}
That's what the compiler generate for you, therefore you do not need to worry about writing such a heavy and repetitive thing which is a possible source of error and bugs.
In the first code, myRespository is not disposed.

Any way to have a `using` block that doesn't define a scope block?

using(var myDisposable = new MyDisposable)
{
//Do stuff.
}
is great and all.
But if what you wanted was:
using(var myDisposable = new MyDisposable)
{
var myAnswer = CalculateMyAnswer(myDisposable);
}
and you wanted to use myAnswer later, then you have to declare myAnswer outside the block, and it's starting to get a bit faffy. :(
Is there any way to declare a using block, but have it not encapsulate scope, so that variables declared inside that block are still visible outside it?
So far my best solution is to just dispose my variable manually:
var myDisposable = new MyDisposable
var myAnswer = CalculateMyAnswer(myDisposable);
myDisposable.Dispose();
but that loses a lot of what I like about using.
Are there any alternatives?
You could add some sugar to it to get rid of the using block in your code with this method:
public static class Disposable
{
public static T Using<R, T>(Func<R> factory, Func<R, T> projection) where R : IDisposable
{
using (var r = factory())
{
return projection(r);
}
}
}
Then you'd just use it like this:
var myAnswer = Disposable.Using(() => new MyDisposable(), m => CalculateMyAnswer(m));
A using statement defines a block. If you want a variable to be accessible outside it you need to define it outside of that block, but you can assign to it in the block:
string myAnswer = null;
using(var myDisposable = new MyDisposable)
{
myAnswer = CalculateMyAnswer(myDisposable);
}

Multithreading in a Single Transaction

According to this MSDN article, you should be able to multithread a process with each thread enlisted in a single root transaction.
I created a sample based on that article where I expect atransaction to be rolled-back (bool[] results should be all false in the foreach loop). Unfortunately, this is not the case, and the outcome is predictably unpredictable (run the example enough times and you will see any combination of bool values in the array).
In addition, I've tried both DependentCloneOption.BlockCommitUntilComplete and DependentCloneOption.RollbackIfNotComplete neither of which produce the expected result.
Secondly, I think ThreadPool.QueueUserWorkItem is ugly code at best, and it would be nice to see something like this using Parallel.ForEach instead.
And finally, my question :) Why the heck is this not working? What am I doing wrong? Is it just flat-out impossible to wrap multiple threads in a single transaction?
namespace Playing
{
class Program
{
static bool[] results = new bool[] { false, false, false };
static void Main(string[] args)
{
try
{
using (var outer = new TransactionScope(
TransactionScopeOption.Required))
{
for (var i = 0; i < 3; i++ )
{
ThreadPool.QueueUserWorkItem(WorkerItem,
new Tuple<int, object>(
i, Transaction.Current.DependentClone(
DependentCloneOption.BlockCommitUntilComplete)));
}
outer.Complete();
}
}
catch { /* Suppress exceptions */ }
// Expect all to be false
foreach (var r in results)
Console.WriteLine(r);
}
private static void WorkerItem(object state)
{
var tup = (Tuple<int, object>)state;
var i = tup.Item1;
var dependent = (DependentTransaction)tup.Item2;
using (var inner = new TransactionScope(dependent))
{
// Intentionally throw exception to force roll-back
if (i == 2)
throw new Exception();
results[i] = true;
inner.Complete();
}
dependent.Complete();
}
}
}
Yours results[] members that have been set to true won't magically set themselves back to false (sadly). That's what Transaction Managers do. Look at the EnlistXXX methods to get an idea of what's involved.
Basically, you'll need to compensate in the event of a rollback. For example, you could subscribe to the root Transaction's TransactionCompleted event and check if the transaction was rolled back. If it was you'll need to restore the previous values for the child workers that completed.
You can also handle the TransactionAbortedException thrown that you are suppressing, or handle it at the worker level (see an example of catching it on this page: http://msdn.microsoft.com/en-us/library/ms973865.aspx)
Typically, with in-memory "transactions" you are better off using the Task library to have the workers batch up results and then "commit" them in a continuation of a parent Task. It's easier than messing about with Transactions, which you only need to do if you are coordinating between memory and some other Transaction Manager (like SQL Server or other processes).

Does `using` dispose all the the objects declared in it?

I wonder if the object created in the usingstatement gets disposed if I perform a return or throw operation. Example as follows.
using(SomeClass thing = new SomeClass())
{
...
if(condition)
return;
...
}
Will the above get confused or is GC to be trusted here?
Yes, it will. The using statement will result in a finally block being created. A finally block's code will be run even if an exception is thrown in the related try block, or if there is a return statement in that try block.
There are only a few exceptions that can cause a finally block's code to not be executed, and they are all listed here, but my guess is that in your situation you'll be able to live with those consequences.
using is the equivalent of try-finally so, yes, it does.
dispose if it is implemented will always get called. Its the equivalent of calling dispose in a finally block.
It will dispose, yes. It will create a finally block in the CIL code.
Yes, because using is extended into a try finally by the compiler. The dispose will occur inside the finally block. Also, the finally will contain a test to check if the variables in the using are null (in case there are exceptions on the constructors).
When writing a using statement:
using(SomeClass thing = new SomeClass())
{
//...
if (condition)
return;
//...
}
this will result in the following code:
SomeClass thing;
try
{
thing = new SomeClass();
//...
if (condition)
return;
//...
}
finally
{
if(thing != null)
{
thing.Dispose();
}
}
So all object declared using ( /* HERE */ ) will get disposed automatically. Objects declared inside the {} won't.
But you can of course nest (or stack) using statements:
using (var thing = new SomeClass())
using (var another = new Another())
using (var somethingElse = new Whatever())
{
//...
}
which in turn of course is just the syntactic sugar for writing
using (var thing = new SomeClass())
{
using (var another = new Another())
{
using (var somethingElse = new Whatever())
{
//...
}
}
}
because when a statement is followed by just one block of code (in this case another using-block) you can skip the curly braces...
When using two or more objects of the same type you can chain the declaratio within the using-statement:
using (MemoryStream stream = new MemoryStream(), stream2 = new MemoryStream())
{
//...
}
(Thanks to #Gratzy for pointing that out)
For me, the question does not match with the details, and the details have been addressed here a bunch but not the title question...
Does using dispose all the the objects declared in it?
NO, it does not. It only calls Dispose() for the object(s) in its declaration. It does not call Dispose() for objects declared in it.
I usually see this kind of thing in code
using(var sqlConn = new SqlConnection("connStr"))
using(var sqlCmd = new SqlCmd("CmdText", sqlConn))
{
sqlConn.Open();
var reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
//stuff is done
}
}
This will dispose and close both sqlConn and sqlCmd when the scope is complete for those but the reader that was declared in the using scope does not have Dispose() automatically called for it .

Is the following pattern acceptable?

I am trying to come up myself with an acceptable pattern for data reading from DB using Enterprise Library. How do you consider the following pattern (I mean, the null-check in the finally block)?
IDataReader NewReader = null;
try
{
NewReader = (SqlDataReader)(SqlDatabase.ExecuteReader(SqlCommand));
/* Do some work with NewReader. */
NewReader.Close();
}
catch /* As much 'catch' blocks as necessary */
{
/* Handle exceptions */
}
finally
{
if (!ReferenceEquals(NewReader, null))
{
NewReader.Dispose();
}
}
Is this null-check acceptable, or is there a more elegant way of solving this problem?
I would use if(NewReader == null). It's the default way of checking for null. Your way of doing it is the same, but it looks strange and thus might confuse people.
Besides: Why don't you use using? Makes your code a lot cleaner:
try
{
using(IDataReader NewReader = (SqlDataReader)(SqlDatabase.ExecuteReader(SqlCommand)))
{
/* Do some work with NewReader. */
}
}
catch /* As much 'catch' blocks as necessary */
{
/* Handle exceptions */
}
It is the same as:
if (NewReader != null) ...
which I would prefer from a styling point of view.
Update:
As NewReader seemingly implements IDisposable, just wrap it in a using construct.
Example:
using (var r = new ReaderSomething())
{
try
{
}
catch {}
}
I would prefer using the "using" block as:
using(<your reader object>)
{
//read data from reader
}
Just to add a bit of detail to what people have said above...
Use a using block as, regardless of whether an exception occurs or not, the Dispose method will automatically be called due to implementations of IDataReader having to also implementing IDisposable.

Categories

Resources