Dealing with nested "using" statements in C# -


i've noticed level of nested using statements has lately increased in code. reason because use more , more of async/await pattern, adds @ least 1 more using cancellationtokensource or cancellationtokenregistration.

so, how reduce nesting of using, code doesn't christmas tree? similar questions have been asked on before, , i'd sum i've learnt answers.

use adjacent using without indentation. fake example:

using (var = new filestream()) using (var b = new memorystream()) using (var c = new cancellationtokensource()) {     // ...  } 

this may work, there's code between using (e.g. may create object):

// ...  using (var = new filestream()) {     // ...      using (var b = new memorystream())     {         // ...          using (var c = new cancellationtokensource())         {             // ...          }     } } 

combine objects of same type (or cast idisposable) single using, e.g.:

// ...  filestream = null; memorystream b = null; cancellationtokensource c = null; // ... using (idisposable a1 = (a = new filestream()),      b1 = (b = new memorystream()),      c1 = (c = new cancellationtokensource())) {     // ...  } 

this has same limitation above, plus more wordy , less readable, imo.

refactor method few methods.

this preferred way, far understand. yet, i'm curious, why following considered bad practice?

public class disposablelist : list<idisposable>, idisposable {     public void dispose()     {         base.foreach((a) => a.dispose());         base.clear();     } }  // ...  using (var disposables = new disposablelist()) {     var = new filestream();     disposables.add(a);     // ...     var b = new memorystream();     disposables.add(b);     // ...     var c = new cancellationtokensource();     disposables.add(c);     // ...  } 

[update] there quite few valid points in comments nesting using statements makes sure dispose called on each object, if inner dispose calls throw. however, there obscure issue: nested exceptions possibly thrown disposing of nested 'using' frames lost, besides outer one. more on here.

in single method, first option choice. in circumstances disposablelist useful. particularly, if have many disposable fields need disposed of (in case cannot use using). implementation given start has few problems (pointed out in comments alexei):

  1. requires remember add item list. (although have remember use using.)
  2. aborts disposal process if 1 of dispose methods throws, leaving remaining items un-disposed.

let's fix 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) t : idisposable     {         var item = factory();         base.add(item);         return item;     } } 

now catch exceptions dispose calls , throw new aggregateexception after going through items. i've added helper add method allows 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());     // ...  } 

Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -