Gestion des ressources : mot clé « use »

Cette rubrique décrit le mot clé use et la fonction using, qui peut contrôler l’initialisation et la libération des ressources.

Ressources

Le terme ressource est utilisé de plusieurs façons. Oui, les ressources peuvent être des données qu’une application utilise, comme des chaînes, des graphiques, etc., mais dans ce contexte, les ressources font référence à des ressources logicielles ou de système d’exploitation, comme des contextes de périphériques graphiques, des descripteurs de fichiers, des connexions réseau et de base de données, des objets de concurrence, comme des descripteurs d’attente, etc. L’utilisation de ces ressources par les applications implique l’acquisition de la ressource auprès du système d’exploitation ou d’un autre fournisseur de ressources, suivie de la publication ultérieure de la ressource dans le pool afin qu’elle puisse être fournie à une autre application. Des problèmes se produisent lorsque les applications ne libèrent pas les ressources dans le pool commun.

Gestion des ressources

Pour gérer efficacement et de manière responsable les ressources dans une application, vous devez libérer les ressources rapidement et de manière prévisible. .NET Framework vous aide à le faire en fournissant l’interface System.IDisposable. Un type qui implémente System.IDisposable a la méthode System.IDisposable.Dispose, qui libère correctement les ressources. Les applications bien écrites garantissent que System.IDisposable.Dispose est appelé rapidement lorsqu’un objet qui contient une ressource limitée n’est plus nécessaire. Heureusement, la plupart des langages .NET prennent cela en charge pour faciliter cette tâche, et F# ne fait pas exception. Il existe deux constructions de langage utiles qui prennent en charge le modèle Dispose : la liaison use et la fonction using.

Utiliser la liaison

Le mot clé use a une forme semblable à celle de la liaison let :

use valeur = expression

Il fournit les mêmes fonctionnalités qu’une liaison let, mais ajoute un appel à Dispose sur la valeur lorsque la valeur sort de l’étendue. Notez que le compilateur insère une vérification null sur la valeur, de sorte que si la valeur est null, l’appel à Dispose n’est pas tenté.

L’exemple suivant montre comment fermer un fichier automatiquement à l’aide du mot clé 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."

Plusieurs instances de use sont supprimées dans l’ordre inverse dans lequel elles sont déclarées. Autrement dit, la première use sera la dernière mise en production.

Remarque

Vous pouvez utiliser use dans les expressions de calcul, auquel cas une version personnalisée de l’expression use est utilisée. Pour plus d’informations, consultez Séquences, Expressions asynchrones, Expressions de tâche et Expressions de calcul.

Fonction using

La fonction using a la forme suivante :

using (expression1) fonction-ou-lambda

Dans une expression using, expression1 crée l’objet qui doit être supprimé. Le résultat d’expression1 (l’objet qui doit être supprimé) devient un argument, valeur, pour fonction-ou-lambda, qui est soit une fonction qui attend un seul argument restant d’un type qui correspond à la valeur produite par expression1, soit une expression lambda qui attend un argument de ce type. À la fin de l’exécution de la fonction, le runtime appelle Dispose et libère les ressources (sauf si la valeur est null, auquel cas l’appel à Dispose n’est pas tenté).

L’exemple suivant illustre l’expression using avec une expression 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 jumps over the lazy brown dog."

L’exemple suivant montre l’expression using avec une fonction.

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

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

Notez que la fonction peut être une fonction avec des arguments déjà appliqués. L'exemple de code suivant illustre cette tâche. Cela crée un fichier qui contient la chaîne XYZ.

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

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

La fonction using et la liaison use sont des façons presque équivalentes d’accomplir la même chose. Le mot clé using offre davantage de contrôle sur le moment où Dispose est appelé. Lorsque vous utilisez using, Dispose est appelé à la fin de la fonction ou de l’expression lambda ; lorsque vous utilisez le mot clé use, Dispose est appelé à la fin du bloc de code contenant. En général, préférez utiliser use plutôt que la fonction using.

Voir aussi