Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Design
Hi,
 
I'd like to hear your opinions on conditional using blocks. The thing is that I need to have a structure like the following:
public void AMethod(bool useClass2) {
   using (Class1 variable1  = new Class1()) {
      using (Class2 variable2 = new Class2(variable1) {
         using (Class3 variable3 = new Class3(variable2) {
            variable3.DoSomething();
         }
      }
   }
}
Now the problem is that based on the parameters of the method the middle using block should either be included or excluded. If the parameter useClass2 is true, the code should be executed as above but if the parameter is false, then the execution should look like the following:
public void AMethod(bool useClass2) {
   using (Class1 variable1  = new Class1()) {
         using (Class3 variable3 = new Class3(variable1) {
            variable3.DoSomething();
         }
   }
}
So based on the parameter, the middle using block may be included and the innermost using block uses either Class1 or Class2.
 
Now, this could be done with for example:
  • Separate, specialized methods (no need for parameter)
  • using If..Else structure for the Class2, and duplicating the inner code on necessary parts etc.
But I'm curious, am I missing something obvious? Would there be an easy, clean way to conditionally use or bypass the instance of the Class2?
 
The classes (1-3) are .Net framework classes derived from File.IO.Stream, for example FileStream, CryptoStream etc.
Posted 12-Sep-12 5:57am
Edited 12-Sep-12 7:00am
v2
Comments
Sergey Alexandrovich Kryukov at 13-Sep-12 22:58pm
   
Hi Mika,
How it's going?
 
Here is the news: I decided to write a short article on this question. I submitted it as a Tips & Tricks article, but by some reason it appeared in Articles section. I provided some of a bit more of in-depth analysis and the source code for the approached I already mentioned in my answer. Here:
http://www.codeproject.com/Articles/458846/Using-using-Statements-DisposalAccumulator
 
I credited you for all of the inspiration you gave by this interesting question and remarkable example.
 
Best wishes,
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

I think separate methods is the way to go. At the very least, the names of those methods could make it more obvious what's going on. Or, if there's no significant penalty to using Class2 even when it's not needed, just use the first.
  Permalink  
Comments
Mika Wendelius at 12-Sep-12 13:27pm
   
Yes, that's one option. In that case I need to duplicate parts of the code but fortunately that's not actually very much.
 
There's no (notable) penalty regarding to performance for using the middle stream, it's just unwanted functionality in that scenario. :)
lewax00 at 12-Sep-12 14:33pm
   
I've done some weird tricks to avoid duplications in the case of re-used using statements with lambdas, it can be a bit awkward though. In the end it doesn't save you much typing, but it can make refactoring easier.
Sergey Alexandrovich Kryukov at 12-Sep-12 20:20pm
   
I think the core thing is: your answer missed the important detail: some essential ambiguity in the question which I explain in my answer -- please see. Good question, anyway.
--SA
Sergey Alexandrovich Kryukov at 13-Sep-12 22:59pm
   
By the way, I decided to publish a short article on this topic. Please see:
http://www.codeproject.com/Articles/458846/Using-using-Statements-DisposalAccumulator
--SA
Mika Wendelius at 14-Sep-12 13:49pm
   
I think still is a good way especially if there's also another parts in the method that are not common. So 5 from me
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

Very interesting question, but yes, you are missing something.
 
Your code sample may mean the different things. Look at the constructor Class2.Class2. It may mean:
 
Single constructor based on late binding of the type Class1:
class Class1 : IDisposable {/* ... */}
 
class Class2 : IDisposable {
   internal Class2(Class1 variable) {/* ... */}
   //...
}
 
// which is based on this inheritance:
class Class2 : Class1, IDisposable {/* ... */}
 
The same code fragments could be implemented in different content, where the classes Class1 and Class2 are unrelated:
class Class2 {
   internal Class2(Class1 variable) {/* ... */}
   internal Class2(Class2 variable) {/* ... */}
   //...
}
 
Are you starting to get it? If you use polymorphism, you can optimize your code and avoid "if":
    static void AMethod(bool useClass2) {
        using (Class1 variable1 = new Class1()) {
            Class1 factoryParameter = null;
            if (useClass2)
                factoryParameter = variable1;
            using (Class1 variable2 = Class1Factory(factoryParameter)) {
                using (Class3 variable3 = new Class3(variable2)) {
                    variable3.DoSomething();
                } //variable3 is disposed here
            } //variable2 is disposed here
        } //variable1 is disposed here
    } //AMethod

    static Class1 Class1Factory(Class1 factoryParameter) { // important: late-bound return type
        if (factoryParameter == null)
            return new Class1();
        else
            return new Class2(factoryParameter);
    } //Class1Factory
 
What to do in the more general case, when those IDisposable classes/structures are unrelated? You can leave your "naive" separate implementation putting both samples together with one "if" operator, but it could look too much messed up if you have greater level of nesting (which easily can be the case).
 
There is another way of doing thing. First, the using statement is equivalent to some try-finally block (or nested blocks). You can literally use it; it can be more compact then using, because try-finally is more general. But you can also use the special and well known technique:
 
Create a special "DisposalAccumulator" class which can accumulate all instances to be disposed in some container. This class should also implement IDisposable, to be used in one single using statement. Create only the instance of such class under using with only one level of nesting. Do you need to explain you more? I thing you should get an idea. If not just yes, your follow-up questions are very welcome — it's always a pleasure to deal with correctly formulated and sensible questions.
 
[EDIT #1]
 
I think most important criterion here would be to avoid any repeated code. I think you understand it. Please see:
http://en.wikipedia.org/wiki/Don%27t_repeat_yourself[^].
 
[EDIT #2]
 
Hold on, I'll try to provide code samples for those two general-case solutions: try-finally and "DisposalAccumulator", because it may be of some value to other readers.
 
My very best wishes,
—SA
  Permalink  
v14
Comments
Mika Wendelius at 14-Sep-12 13:46pm
   
Yes, this would be a feasible solution especially with own classes. Definitely a five.
Sergey Alexandrovich Kryukov at 14-Sep-12 14:25pm
   
Thank you, Mika.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 5

I landed here via the article[^] proposed by Sergey, but I'm sure you'd like to see my solution as well.
 
You can actually assign null values to using statement variables. The syntactic sugar for the using block actually checks for a null variable in the finally block prior to a dispose. So, per Sergey's example, I provided the following solution that reduces redundant code and doesn't require the need for an additional class:
 
static void NotSoNaiveWay(bool createSecond)
{
    using (First first = new First())
    using (Second second = (createSecond) ? new Second(first) : null)
    using (Third third = (createSecond) ? new Third(second) : new Third(first))
    {
        third.DoSomething();
    }
}
 
If you made the Third class dispose of any provided IDisposable elements, you could simplify this further to:
 
static void NotSoNaiveWay(bool createSecond)
{
    using (First first = new First())
    using (Third third = (createSecond) ? new Third(new Second(first)) : new Third(first))
    {
        third.DoSomething();
    }
}
 
I hope that helps.
  Permalink  
Comments
Mika Wendelius at 14-Sep-12 13:51pm
   
Thanks, I actually was thinking the same :) The only concern I have is that this solution relies on the fact that Dispose isn't called for a null. This is current behaviour in .Net but could this be a potential breaking change...
 
Anyhow, this works nicely currently so a 5.
Andrew Rissing at 14-Sep-12 14:06pm
   
I don't believe I've heard any mumblings of this behavior changing any time soon. So, you are likely safe for sometime.
 
Btw, are you using this to conditionally encrypt/compress your output? Or is this for something else?
Mika Wendelius at 14-Sep-12 15:28pm
   
Basically this is for a project I'm working with which includes compression and encryptions so a good guess :)
 
As a spin-off I was thinking about using it on the article I updated: Encrypting a dataset using AES, including compression[^] but then I decided not to, since I believe that it would have (possibly) been harder to read.
Andrew Rissing at 14-Sep-12 15:58pm
   
Cool. I will say though that GZipStream and CryptoStream both dispose of any Stream objects passed to them, so the use of layered using statements would be redundant. Worst case scenario, if the dispose method failed to complete successfully (an entirely exceptional situation here), the finalize method would eventually kick in as a saving grace.
 
Food for thought.
Mika Wendelius at 14-Sep-12 16:05pm
   
Thanks, that's really messing my brains in late Friday night (local time) :)
 
Now professionally, yes you're right, it would be redundant but since they are disposed in correct order I also think that the finalizer will handle the situation :)
Andrew Rissing at 14-Sep-12 16:13pm
   
Either way, they would be handled properly. The finalizer would be only called if Dispose was somehow missed.
 
It is up to you whether or not to use the additional using statements for completeness, but ultimately they really shouldn't be necessary.
 
Anyways, enjoy the weekend. I'll be there shortly myself.
Mika Wendelius at 14-Sep-12 16:14pm
   
That's true. Have a nice weekend!
Sergey Alexandrovich Kryukov at 14-Sep-12 14:26pm
   
I did not know you posted this as an answer as well -- it was a good idea of you to do so. My 5.
--SA
Andrew Rissing at 14-Sep-12 15:16pm
   
Thanks. :)
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

In this case I would probably have separate public methods and call a common private method if you need to reduce code duplication. An option would be to use a generic in the private class. Can also just use the generic in a public class. Here is the general concept:
 
public void Test1 ()
{
    Test<test1>();
}
 
public void Test2()
{
    Test<test2>();
}
 
private void Test<T> () where T : IDisposable, new()
{
    using (var x = new T())
    {
 
    }
}
  Permalink  
Comments
Mika Wendelius at 12-Sep-12 14:12pm
   
Hmm, yes that could work fine in this situation. Converting the idea to the example I wrote, I'd actually link the methods and make the decision which method to use in the outermost using block.
 
What I need to check is that can I use the base class definition (Stream in this case) in the innermost method and still achieve the same functionality. If this would be true, I could use this idea to reduce the code duplication.
 
Of course on the other hand this raises the complexity a bit but I'm curious to see how it actually turns out :)
Clifford Nelson at 12-Sep-12 15:01pm
   
To ensure that it is a stream, obviously add to the where clause. The complexity, I think, is actually less. The streams already support IDisposable. Also, can just make the Test public, which would make it much more flexible, expecially if it is designed to work with any instance of a class that inherits from a base class.
Sergey Alexandrovich Kryukov at 12-Sep-12 20:22pm
   
Good point, but I voted 4, just because it's hard to see how it can improve the code with nesting and depending IDisposable variables. I, for example, cannot see it. I would suggest you demonstrate the use of those 2 vs 3 variables and how they are disposed.
 
There is another important thing here: some essential ambiguity in the question which I explain in my answer -- please see. Good question, anyway.
--SA
Sergey Alexandrovich Kryukov at 13-Sep-12 23:00pm
   
By the way, I decided to publish a short article on this topic. Please see:
http://www.codeproject.com/Articles/458846/Using-using-Statements-DisposalAccumulator
--SA
Mika Wendelius at 14-Sep-12 13:48pm
   
Just tested this variation and it works out fine. The only problem that I encountered was that the logic is easily scattered to separate methods (depending on the situation). Anyhow a usable solution in many cases.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Why dont you go for inheritance ?
 
Class3 > Inherits Class2
Class2 > Inherits Class1
 
Now Implement Class1 as IDisposable, and you will be able to use Single using statement
 
Also define proper methods and constructors that act on specific objects.
  Permalink  
Comments
Mika Wendelius at 12-Sep-12 12:59pm
   
Good point. One thing I forgot to mention is that the classes are actually .Net Framework classes, to be precise, different kinds of streams derived from File.IO.Stream.
 
I'll update the question
Sergey Alexandrovich Kryukov at 12-Sep-12 20:19pm
   
Maybe, but, unfortunately, if does not solve the problem per se. Besides, most answers miss the important detail: some essential ambiguity in the question which I explain in my answer -- please see. Good question, anyway.
--SA
Kuthuparakkal at 13-Sep-12 1:45am
   
You may get more ideas on this by examining open source SharpZipLib classes, they have many classes that inherit from System.IO.Stream:
http://www.icsharpcode.net/opensource/sharpziplib/Download.aspx
Mika Wendelius at 13-Sep-12 5:08am
   
Thanks! I'll have a look at those.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 490
1 Gihan Liyanage 338
2 ChauhanAjay 180
3 Vinay Mistry 160
4 Sergey Alexandrovich Kryukov 153
0 Sergey Alexandrovich Kryukov 9,011
1 OriginalGriff 7,941
2 CPallini 2,603
3 Richard MacCutchan 2,121
4 Abhinav S 1,928


Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 14 Sep 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100