using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection cn = new SqlConnection())
{
// do stuff
}
ts.Complete();
}I don’t have really any problem with this kind of nesting because it shows a clear separation between blocks which have different purposes. In fact I really like it. It also clearly shows the nesting hierarchy. A TransactionScope has a different logical meaning than a SqlConnection, so it seems a lot better to create nested blocks to show this relationship.
Nick Randolph is answering with a Vb.Net example which allow the declaration of multiple disposable resources in just one block, which allow statements like
Using ts As New TransactionScope(), cn As New SqlConnection()
' do stuff
ts.Complete()
End Using
Under the hood the Vb.Net compiler is generating the nested usings, which is probably what Rory wants. Personally, I don’t like this way of writing nested using is potentially too confusing as I explained previously.
In fact C# is supporting a similar way of declaring nested using but only for resources of the same type, which is really nice for disposable resources which are on the same semantic level (like 2 connections inside a distrbuted transactions)
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection cn1 = new SqlConnection(), cn2 = new SqlConnection())
{
// do stuff
}
}
Forcing a little bit the things, for guys which really hate nested usings (not me), you can declare any type of disposable resource in a using list, because all of them are IDisposable.
using (IDisposable d1 = new TransctionScope(), d2 = new SqlConnection())
{
TransactionScope ts = (TransactionScope)d1;
SqlConnection cn = (SqlConnection)d2;
// do stuff
}
Of course you need to cast inside the block in order to use the disposable resource at full power.
Or another trick for C# nested using haters. Define a list DisposableList : List<IDisposable> and use it like that
TransactionScope ts;
SqlConnection sc;
using (new DisposableList().Add(ts = new TransactionScope()).Add(sc = new SqlConnection()))
{
// do stuff
}
I don’t like these tricks and I don’t use them. I prefer nested usings + using with multiple resources of the same type, which is a lot clearer and without potentially wrong usages.
Continuing with the using/IDisposable story, what Nick wants (automatically call to Dispose method for stack-method variable declared resources) is not something which can be solved at the level of the compiler. The C++ compiler is in fact as dumb as the C# one. The C++ compiler doesn’t do any magic under the hood for automatically call the Dispose method. The magic is in fact just a syntactic sugar of the C++ language.
In C++/CLI you have 2 ways to declare a stack/method variable:
1. RefType ^ref = gcnew RefType();
2. RefType ref;
Both declarations, besides looking extremely different have the same result. A RefType instance is allocated on the heap. The difference is that the second one is binding syntactically the “ref” to the local scope, so the compiler can insert the call to Dispose at the end of the scope. So is just a syntax trick, not that the compiler is more intelligent.
No comments:
Post a Comment