Gestione di risorse: parola chiave use (F#)

In questo argomento vengono descritte la parola chiave use e la funzione using, che consentono di controllare l'inizializzazione e il rilascio delle risorse.

Risorse

Il termine risorsa viene utilizzato in più modi. Le risorse possono essere dati utilizzati da un'applicazione, ad esempio stringhe, grafici e così via, ma, in questo contesto, le risorse si riferiscono a risorse software o del sistema operativo, ad esempio contesti di dispositivi grafici, handle di file, connessioni di rete e database, oggetti di concorrenza, ad esempio handle di attesa, e così via. L'utilizzo di queste risorse da parte delle applicazioni comporta l'acquisizione della risorsa dal sistema operativo o da un altro provider di risorse, seguita dal successivo rilascio della risorsa al pool, in modo che possa essere fornita a un'altra applicazione. Quando le applicazioni non rilasciano di nuovo le risorse al pool comune, si verificano problemi.

Gestione delle risorse

Per gestire le risorse in modo efficiente e responsabile in un'applicazione, è necessario rilasciarle in modo tempestivo e prevedibile. A tale scopo, in .NET Framework viene fornita l'interfaccia IDisposable. Un tipo che implementa IDisposable dispone del metodo Dispose, in grado di rilasciare correttamente le risorse. Le applicazioni ben scritte garantiscono che il metodo Dispose venga chiamato tempestivamente quando un oggetto che trattiene una risorsa limitata non è più necessario. Fortunatamente, la maggior parte dei linguaggi .NET fornisce supporto per semplificare questa procedura e lo stesso avviene in F#. Sono disponibili due utili costrutti di linguaggio che supportano il modello di eliminazione: l'associazione use e la funzione using.

Associazione use

La parola chiave use ha un forma simile a quella dell'associazione let:

use value = expression

Fornisce la stessa funzionalità di un'associazione let, aggiungendo tuttavia una chiamata a Dispose sul valore quando esce dall'ambito. Il compilatore inserisce un controllo null sul valore, in modo che se il valore è null, non viene eseguito il tentativo di chiamare Dispose.

Nell'esempio seguente viene illustrato come chiudere automaticamente un file utilizzando la parola chiave use.

open System.IO

let writetofile filename obj =
   use file1 = File.CreateText(filename)
   file1.WriteLine("{0}", obj.ToString() )
   // file1.Dispose() is called implicitly here.

writetofile "abc.txt" "Humpty Dumpty sat on a wall."

Nota

È possibile utilizzare use nelle espressioni di calcolo, nel qual caso viene utilizzata una versione personalizzata dell'espressione use.Per ulteriori informazioni, vedere Sequenze (F#), Flussi di lavoro asincroni (F#) e Espressioni di calcolo (F#).

Funzione using

La funzione using presenta la forma seguente:

using (expression1) function-or-lambda

In un'espressione using, expression1 creare l'oggetto che è necessario eliminare. Il risultato di expression1 (l'oggetto che deve essere eliminato) diventa un argomento, value di function-or-lambda, che è una funzione che prevede un singolo argomento restante di un tipo che corrisponde al valore prodotto da expression1 o un'espressione lambda che prevede un argomento di tale tipo. Al termine dell'esecuzione della funzione, il runtime chiama Dispose e libera le risorse (a meno che il valore non sia null, nel qual caso non viene effettuato il tentativo di chiamare Dispose).

Nell'esempio seguente viene illustrata l'espressione using con un'espressione lambda.

open System.IO

let writetofile2 filename obj =
    using (System.IO.File.CreateText(filename)) ( fun file1 ->
        file1.WriteLine("{0}", obj.ToString() )
    )

writetofile2 "abc2.txt" "The quick sly fox jumped over the lazy brown dog."

Nell'esempio successivo viene illustrata l'espressione using con una funzione.

let printToFile (file1 : System.IO.StreamWriter) =
    file1.WriteLine("Test output");

using (System.IO.File.CreateText("test.txt")) printToFile

Si noti che alla funzione potrebbero già essere applicati alcuni argomenti. Nell'esempio di codice che segue viene illustrata questa possibilità. Viene creato un file contenente la stringa XYZ.

let printToFile2 obj (file1 : System.IO.StreamWriter) =
    file1.WriteLine(obj.ToString())

using (System.IO.File.CreateText("test.txt")) (printToFile2 "XYZ")

La funzione using e l'associazione use sono modalità quasi equivalenti per ottenere lo stesso risultato. La parola chiave using fornisce un maggiore controllo sui tempi di chiamata di Dispose. Quando si utilizza using, il metodo Dispose viene chiamato alla fine della funzione o dell'espressione lambda, mentre quando si utilizza la parola chiave use, Dispose viene chiamato alla fine del blocco di codice che lo contiene. In generale, è preferibile utilizzare use anziché la funzione using.

Vedere anche

Riferimenti

IDisposable

Altre risorse

Riferimenti per il linguaggio F#