Principale utente con più risposte
Corretto utilizzo di Using..End Using

Domanda
-
Ciao e grazie a tutti per le stupende risposte!
Adesso ho capito la differenza!
Vi pongo un ultimo quesito, che spesso ho incontrato e mai appreso bene..
Come si sfruttano gli using <...> end using in modo corretto?
Sopratutto, quando si arriva all'end using viene chiamata la iDisposable in automatico?
Tale iDisposable se ho ben capito serve a rilasciare le risorse non più necessarie, come ad esempio oggetti instanziati.. però non mi è chiaro come essa vada scritta...
Per tornare ad argomenti pratici, mettiamo questo esempio che uso per leggere un file di testo.
Imports System.IO Public Class Lettura Public Function Leggi(ByVal Path As String) As String Dim sr As StreamReader = New StreamReader(Path) Return sr.ReadToEnd End Function End Class
Come potrei implementare l'iDisposable? e come poi conviene usare gli using end using in maniera corretta nella form che instanzia ed usa tale classe?
Grazie davvero a tutti!
- Split Alessandro Del Sole [MVP]MVP mercoledì 27 ottobre 2010 15:48 Domanda nidificata altrimenti difficile da individuare nel thread
Risposte
-
Il blocco Using ... End Using aiuta il programmatore nell'utilizzare correttamente tutte le classi che implementano IDisposable. Tipicamente se una classe implementa IDisposable significa che è necessario richiamarne il metodo Dispose perchè alcune azioni importanti (ad esempio il rilascio di risorse, la chiusura di files, connessioni, ecc...) viene esplicitamente effettuata dal codice scritto all'interno di questo metodo. Il metodo Dispose è inoltre richiamato automaticamente quando il Garbage Collector distrugge la classe (spero tu sappia come viene gestito il GC nel framework...), quindi prima o poi qualcuno quel codice lo richiamerà. Se tu lasci che il compito venga gestito dal GC può verificarsi qualche problema, perchè non sai esattamente quando la tua classe verrà distrutta poichè, essendo il GC un processo gestito dal SO, tu non ne hai il controllo diretto (a meno che non lo gestisci da codice attraverso il meccanismo offerto dall'intertfaccia IDispose). In due parole Using ... End Using ti risolve il problema. Analizziamo questi due frammenti di codice:
Public Function Leggi(ByVal Path As String) As String Dim sr As StreamReader = New StreamReader(Path) Return sr.ReadToEnd End Function Public Function Leggi(ByVal Path As String) As String Dim RetValue as String Using sr As New StreamReader (Path) RetValue = sr.ReadToEnd End Using Return RetValue End Function
ll primo frammento apre uno stream reader, legge una variabile e la ritorna come valore (addirittura per riferimento!!!!). Non leggo nessun codice che chiuda il file letto che ovviamente rimane aperto finchè l'oggetto sr non viene distrutto (ATTENZIONE!!!! Uscire dall'area di validità NON significa distruggere la classe StreamReader).
Nel secondo frammento invece utilizzi uno stream reader all'interno di un blocco Using ... End Using, questo significa che il metodo Dispose dell'oggetto sr viene richiamato automaticamente dall'End Using, si presume che il metodo Dispose abbia al suo interno (e così è) il codice che chiude il file aperto facendoti dormire sonni tranquilli.
In linea di massima ogni volta che usi una classe che implementa l'interfaccia IDisposable sarebbe corretto richiamarne il metodo Dispose oppure utilizzarla all'interno di un blocco Using ... End Using.
Un'ulteriore raccomandazione è quella di evitare di richiamare esplicitamente i metodi del GC poichè molto dispendiosi da un punto di vista di allocazione di risorse.
HTH
Alberto De Luca [MVP - Visual Basic .NET]- Proposto come risposta Mila Daniel Ovidiu giovedì 28 ottobre 2010 11:17
- Contrassegnato come risposta Mila Daniel Ovidiu lunedì 1 novembre 2010 13:33
-
Non tutte le tue classi hanno la necessità di implementare la IDisposable.
In generale una tua classe è opportuno implementi la IDisposable quando uno dei suoi attributi implementa IDisposable e, quindi, hai la necessità di avere un punto in cui richiamare su di esso Dispose, oppure se uno dei suoi attributi è il riferimento ad un oggetto unmanaged (ad esempio un riferimento ad un oggetto COM) o se hai grosse quantità di dati da rilasciare.
In tutti gli alti casi non hai la necessità di implementare IDisposable.- Proposto come risposta Mila Daniel Ovidiu giovedì 28 ottobre 2010 11:17
- Contrassegnato come risposta Mila Daniel Ovidiu lunedì 1 novembre 2010 13:33
-
Se può interessarti, per capire la gestione del ciclo di vita di un oggetto .NET e come/quando implementare IDisposable, ti puoi scaricare gratuitamente il capitolo 8 del mio libro "VB 2010 Unleashed" dal titolo "Managing an object's lifetime". Lo trovi qui:
http://msdn.microsoft.com/en-us/vbasic/bb897562.aspx
Alessandro Del Sole
Microsoft MVP - Visual Basic: development
http://community.visual-basic.it/alessandro/- Contrassegnato come risposta Mila Daniel Ovidiu lunedì 1 novembre 2010 13:33
Tutte le risposte
-
Il blocco Using ... End Using aiuta il programmatore nell'utilizzare correttamente tutte le classi che implementano IDisposable. Tipicamente se una classe implementa IDisposable significa che è necessario richiamarne il metodo Dispose perchè alcune azioni importanti (ad esempio il rilascio di risorse, la chiusura di files, connessioni, ecc...) viene esplicitamente effettuata dal codice scritto all'interno di questo metodo. Il metodo Dispose è inoltre richiamato automaticamente quando il Garbage Collector distrugge la classe (spero tu sappia come viene gestito il GC nel framework...), quindi prima o poi qualcuno quel codice lo richiamerà. Se tu lasci che il compito venga gestito dal GC può verificarsi qualche problema, perchè non sai esattamente quando la tua classe verrà distrutta poichè, essendo il GC un processo gestito dal SO, tu non ne hai il controllo diretto (a meno che non lo gestisci da codice attraverso il meccanismo offerto dall'intertfaccia IDispose). In due parole Using ... End Using ti risolve il problema. Analizziamo questi due frammenti di codice:
Public Function Leggi(ByVal Path As String) As String Dim sr As StreamReader = New StreamReader(Path) Return sr.ReadToEnd End Function Public Function Leggi(ByVal Path As String) As String Dim RetValue as String Using sr As New StreamReader (Path) RetValue = sr.ReadToEnd End Using Return RetValue End Function
ll primo frammento apre uno stream reader, legge una variabile e la ritorna come valore (addirittura per riferimento!!!!). Non leggo nessun codice che chiuda il file letto che ovviamente rimane aperto finchè l'oggetto sr non viene distrutto (ATTENZIONE!!!! Uscire dall'area di validità NON significa distruggere la classe StreamReader).
Nel secondo frammento invece utilizzi uno stream reader all'interno di un blocco Using ... End Using, questo significa che il metodo Dispose dell'oggetto sr viene richiamato automaticamente dall'End Using, si presume che il metodo Dispose abbia al suo interno (e così è) il codice che chiude il file aperto facendoti dormire sonni tranquilli.
In linea di massima ogni volta che usi una classe che implementa l'interfaccia IDisposable sarebbe corretto richiamarne il metodo Dispose oppure utilizzarla all'interno di un blocco Using ... End Using.
Un'ulteriore raccomandazione è quella di evitare di richiamare esplicitamente i metodi del GC poichè molto dispendiosi da un punto di vista di allocazione di risorse.
HTH
Alberto De Luca [MVP - Visual Basic .NET]- Proposto come risposta Mila Daniel Ovidiu giovedì 28 ottobre 2010 11:17
- Contrassegnato come risposta Mila Daniel Ovidiu lunedì 1 novembre 2010 13:33
-
Non tutte le tue classi hanno la necessità di implementare la IDisposable.
In generale una tua classe è opportuno implementi la IDisposable quando uno dei suoi attributi implementa IDisposable e, quindi, hai la necessità di avere un punto in cui richiamare su di esso Dispose, oppure se uno dei suoi attributi è il riferimento ad un oggetto unmanaged (ad esempio un riferimento ad un oggetto COM) o se hai grosse quantità di dati da rilasciare.
In tutti gli alti casi non hai la necessità di implementare IDisposable.- Proposto come risposta Mila Daniel Ovidiu giovedì 28 ottobre 2010 11:17
- Contrassegnato come risposta Mila Daniel Ovidiu lunedì 1 novembre 2010 13:33
-
Se può interessarti, per capire la gestione del ciclo di vita di un oggetto .NET e come/quando implementare IDisposable, ti puoi scaricare gratuitamente il capitolo 8 del mio libro "VB 2010 Unleashed" dal titolo "Managing an object's lifetime". Lo trovi qui:
http://msdn.microsoft.com/en-us/vbasic/bb897562.aspx
Alessandro Del Sole
Microsoft MVP - Visual Basic: development
http://community.visual-basic.it/alessandro/- Contrassegnato come risposta Mila Daniel Ovidiu lunedì 1 novembre 2010 13:33