Ressourcenverwaltung: Das use-Schlüsselwort (F#)

In diesem Thema werden das use-Schlüsselwort und die using-Funktion beschrieben, mit denen die Initialisierung und Freigabe von Ressourcen gesteuert werden kann.

Ressourcen

Der Begriff Ressource wird auf unterschiedliche Weise verwendet. Ressourcen können zwar auch von einer Anwendung verwendete Daten sein, z. B. Zeichenfolgen, Grafiken und Ähnliches, in diesem Kontext jedoch bezeichnet der Begriff Ressourcen Software- oder Betriebssystemressourcen, z. B. Grafikgerätekontexte, Dateihandles, Netzwerk- und Datenbankverbindungen, Parallelitätsobjekte, beispielsweise Wait-Handles, usw. Für die Verwendung dieser Ressourcen durch Anwendungen wird die Ressource vom Betriebssystem oder einem anderen Ressourcenanbieter abgerufen, und später wird die Ressource für den Pool freigegeben, damit sie für eine andere Anwendung bereitgestellt werden kann. Wenn Anwendungen Ressourcen nicht wieder für den gemeinsamen Pool freigeben, treten Probleme auf.

Verwalten von Ressourcen

Für die effiziente und umsichtige Verwaltung von Ressourcen in einer Anwendung müssen Sie Ressourcen zeitnah und berechenbar freigeben. .NET Framework unterstützt Sie dabei durch die Bereitstellung der IDisposable-Schnittstelle. Ein Typ, der IDisposable implementiert, verfügt über die Dispose-Methode, die Ressourcen ordnungsgemäß freigibt. Gut geschriebene Anwendungen gewährleisten den unverzüglichen Aufruf von Dispose, wenn ein Objekt, das eine begrenzte Ressource enthält, nicht mehr benötigt wird. Glücklicherweise stellen die meisten .NET-Sprachen Unterstützung bereit, um dies zu erleichtern, und F# ist keine Ausnahme. Es gibt zwei hilfreiche Sprachkonstrukte, die das Dispose-Muster unterstützen: die use-Bindung und die using-Funktion.

use-Bindung

Die Form des use-Schlüsselworts ähnelt der Form der let-Bindung:

use value = expression

Die use-Bindung bietet die gleiche Funktionalität wie eine let-Bindung, jedoch wird zusätzlich Dispose für den Wert aufgerufen, wenn der Wert nicht mehr im Gültigkeitsbereich liegt. Der Compiler fügt eine NULL-Überprüfung in den Wert ein, damit Dispose nicht aufgerufen wird, wenn der Wert null ist.

Im folgenden Beispiel wird gezeigt, wie mithilfe des use-Schlüsselworts eine Datei automatisch geschlossen wird.

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."

Tipp

Sie können use in Berechnungsausdrücken verwenden. In diesem Fall wird eine benutzerdefinierte Version des use-Ausdrucks verwendet. Weitere Informationen finden Sie unter Sequenzen (F#), Asynchrone Workflows (F#) und Berechnungsausdrücke (F#).

using-Funktion

Die using-Funktion weist die folgende Form auf:

using (expression1) function-or-lambda

In einem using-Ausdruck erstellt expression1 das Objekt, das freigegeben werden muss. Aus dem Ergebnis von expression1 (das Objekt, das freigegeben werden muss) wird das Argument value für function-or-lambda. Dies ist entweder eine Funktion, die ein einzelnes restliches Argument eines Typs erwartet, der mit dem von expression1 erzeugten Wert übereinstimmt, oder ein Lambda-Ausdruck, der ein Argument dieses Typs erwartet. Am Ende der Ausführung der Funktion ruft die Laufzeit Dispose auf und gibt die Ressourcen frei, außer wenn der Wert null ist. In diesem Fall, wird "Dispose" nicht aufgerufen.

Im folgenden Beispiel wird der using-Ausdruck mit einem Lambda-Ausdruck veranschaulicht.

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."

Das nächste Beispiel veranschaulicht den using-Ausdruck mit einer Funktion.

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

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

Beachten Sie, dass es sich bei der Funktion um eine Funktion handeln kann, auf die bereits einige Argumente angewendet wurden. Dies wird im folgenden Codebeispiel dargestellt. In ihm wird eine Datei erstellt, die die Zeichenfolge XYZ enthält.

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

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

Die using-Funktion und die use-Bindung sind nahezu äquivalente Verfahren, um das gleiche Ergebnis zu erreichen. Das using-Schlüsselwort bietet mehr Kontrolle über den Zeitpunkt des Aufrufs von Dispose. Wenn Sie using verwenden, wird Dispose am Ende der Funktion oder des Lambda-Ausdrucks aufgerufen. Wenn Sie das use-Schlüsselwort verwenden, wird Dispose am Ende des enthaltenden Codeblocks aufgerufen. Im Allgemeinen empfiehlt es sich, die use- statt der using-Funktion zu verwenden.

Siehe auch

Referenz

IDisposable

Weitere Ressourcen

F#-Sprachreferenz