Clause "Using" di C#

Ho appena finito di ramazzare un po di codice in cui veniva pesantemente usata la clause "Using" di C#. Per chi non lo sapesse in pratica è un "sintactic sugar" che non fa altro che incapsulare dentro un try...catch...finally la variabile usata dentro lo using.

Quindi un costrutto del tipo

using(SqlConnection cn = new SqlConnection()) {..}
catch {...}

è equivalente a

SqlConnection cn;
try {
 cn=new SqlConnection();
}
catch {...}
finally {
in(null!=cn)
  cn.Dispose();
}

Il risultato è che il codice è più compatto, dal punto di vista dell'IL generato non cambia nulla.

Cambia però, a mio avviso, la mantenibilità del codice, perchè quella che era partito come un codice semplice nel giro di poche modifiche è diventato quello che segue

using(SqlConnection cn = new SqlConnection()) {
SqlCommand cm = cn.CreateCommand();
SqlTransaction tn = cn.BeginTransaction();
cm.Transaction = tn;
}
catch {...}
In pratica quindi mi ritrovo ad aver generato 2 nuove variabili (di oggetti che implementano la IDisposable) e di cui nessuno farà mai la dispose. Quindi o rimuovo la Using mettendo una try...catch...finally oppure (se, come nel caso in questione, in codice è stato fatto da una persona poco esperta) me lo scordo. Non dico che con la finally scritta in modo esplicito tutti poi si ricordano di fare la Dispose di tutto, ma se lo vedi scritto in maniera esplicita magari il dubbio ti viene...

Con tutto questo cosa voglio dire???? Nulla, ma i fatti mi cosano. E la Using è male. Ed in generale mettere in un linguaggio dei costrutti che non siano altro che "sintactic sugar" probabilmente è altettanto un male.

[Edit]
Un commento veloce sul discorso di indentare gli using. Scusa ma (è un parere personale) sto codice non mi piace:

using (SqlConnection cn = new SqlConnection()) {
  using (SqlCommand cm = cn.CreateCommand()) {
    using(SqlTransaction tn = cn.BeginTransaction ()) {
...
    }
  }
}

Ma ripeto, è un parere personale. Tecnicamente il problema può essere che implicitamente crea un "catch stack" abbastanza profondo, quindi nel momento in cui hai un'eccezione nello strato interno questa deve navigare 3 catch per risalire.

Sugli altri sono abbastanza d'accordo, se il programmatore zuccone non mi fa le Dispose si incasina in un modo e nell'altro, l'unica cosa è che se il codice è esplicito magari gli viene in mente di capire perchè esiste quella Dispose in fondo e magari si istruisce...

posted @ giovedì 13 settembre 2007 13:48

Print

Comments on this entry:

# re: Clause "Using" di C#

Left by Alessio at 13/09/2007 16:08
Gravatar
Ciao, capisco il tuo punto di vista ma non mi trovo d'accordo col dire che lo using è male. Come tutte le cose si deve saper usare correttamente, e in tanti sbaglieranno, ma saranno spesso e volentieri gli stessi che non avrebbero neppure messo il finally. Mi spiego meglio: io consiglio sempre l'istruzione using perchè ho notato che spesso istruzioni finally con dentro la chiamata alla Dispose() nel codice non vengono messe, ed ecco che convincerli e istruirli ad usare lo using è più semplice. Inoltre il codice finale lo trovo molto più leggibile. Ribadisco però: è solo un modo diverso di scrivere la stessa cosa, come hai giustamente fatto notare, e va tutto bene se a usare certi costrutti è qualcuno che ha presente cosa significa fare la dispose e perchè sia importante. Chi ha presente certi concetti userà correttamente il try-finally come userà correttamente gli using, mentre gli altri faranno casini con entrambi. Forse, a mio modesto avviso e per mia esperienza, leggermente meno con lo using, ma sono differenze minime.
Ciao

# re: Clause "Using" di C#

Left by Lorenzo Barbieri at 13/09/2007 19:35
Gravatar
Concordo con Alessandro e Matteo...

# re: Clause "Using" di C#

Left by korkless at 16/11/2007 17:48
Gravatar
nonostante mi sia anch'io abituato all'utilizzo dello using volevo solo far notare un'enorme errore che appare nel tuo codice (l'ho scoperto anch'io da poco) e che evidenzia un problema dovuto all'utilizzo di sugar cioà a non sapere chiaramente come viene interpretato il codice.

Nel caso dello using in realtà il costruttore viene invocato fuori dal try, cioè se il costruttore lancia un eccezione non viene chiamato Dispose.

Per chi è interessato l'ho scoperto in questo libro online
http://www.albahari.com/threading/
Comments have been closed on this topic.