Resourcebeheer: het gebruik van trefwoord
In dit onderwerp worden het trefwoord use
en de using
functie beschreven, waarmee u de initialisatie en release van resources kunt beheren.
Resources
De termresource wordt op meer dan één manier gebruikt. Ja, resources kunnen gegevens zijn die een toepassing gebruikt, zoals tekenreeksen, afbeeldingen en dergelijke, maar in deze context verwijzen resources naar software- of besturingssysteembronnen, zoals contexten van grafische apparaten, bestandsingangen, netwerk- en databaseverbindingen, gelijktijdigheidsobjecten zoals wachtgrepen, enzovoort. Het gebruik van deze resources door toepassingen omvat de verwerving van de resource van het besturingssysteem of een andere resourceprovider, gevolgd door de latere release van de resource in de pool, zodat deze aan een andere toepassing kan worden verstrekt. Er treden problemen op wanneer toepassingen geen resources vrijgeven aan de gemeenschappelijke pool.
Resources beheren
Als u resources in een toepassing efficiënt en verantwoord wilt beheren, moet u resources onmiddellijk en op een voorspelbare manier vrijgeven. Het .NET Framework helpt u dit te doen door de System.IDisposable
interface te bieden. Een type dat wordt geïmplementeerd System.IDisposable
, heeft de System.IDisposable.Dispose
methode, waarmee resources correct worden vrijgemaakt. Goed geschreven toepassingen garanderen dat deze System.IDisposable.Dispose
onmiddellijk worden aangeroepen wanneer een object dat een beperkte resource bevat niet meer nodig is. Gelukkig bieden de meeste .NET-talen ondersteuning om dit eenvoudiger te maken, en F# is geen uitzondering. Er zijn twee nuttige taalconstructies die ondersteuning bieden voor het verwijderingspatroon: de use
binding en de using
functie.
Binding gebruiken
Het use
trefwoord heeft een formulier dat lijkt op die van de let
binding:
waarde-expressie = gebruiken
Het biedt dezelfde functionaliteit als een let
binding, maar voegt een aanroep toe aan Dispose
de waarde wanneer de waarde buiten het bereik valt. Houd er rekening mee dat de compiler een null-controle op de waarde invoegt, zodat de aanroep naar Dispose
de waarde niet wordt geprobeerd als de waarde isnull
.
In het volgende voorbeeld ziet u hoe u een bestand automatisch sluit met behulp van het use
trefwoord.
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."
Meerdere exemplaren worden use
verwijderd in de omgekeerde volgorde waarin ze worden gedeclareerd. Dat wil gezegd, de eerste use
zal de laatste zijn die is uitgebracht.
Notitie
U kunt in berekeningsexpressies gebruiken use
. In dat geval wordt een aangepaste versie van de use
expressie gebruikt. Zie Reeksen, Asynchrone expressies, taakexpressies en rekenexpressies voor meer informatie.
functie gebruiken
De using
functie heeft de volgende vorm:
using
(expression1) functie-of-lambda
In een using
expressie maakt expression1 het object dat moet worden verwijderd. Het resultaat van expressie1 (het object dat moet worden verwijderd) wordt een argument, waarde, functie-of-lambda. Dit is een functie die één resterend argument verwacht van een type dat overeenkomt met de waarde die is geproduceerd door expressie1, of een lambda-expressie die een argument van dat type verwacht. Aan het einde van de uitvoering van de functie worden de resources door de runtime aangeroepen Dispose
en vrijgemaakt (tenzij de waarde is null
, in welk geval de aanroep om te verwijderen niet wordt geprobeerd).
In het volgende voorbeeld ziet u de using
expressie met een lambda-expressie.
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."
In het volgende voorbeeld ziet u de using
expressie met een functie.
let printToFile (file1 : System.IO.StreamWriter) =
file1.WriteLine("Test output");
using (System.IO.File.CreateText("test.txt")) printToFile
Houd er rekening mee dat de functie een functie kan zijn waarop al enkele argumenten zijn toegepast. In het volgende codevoorbeeld ziet u dit. Er wordt een bestand gemaakt dat de tekenreeks XYZ
bevat.
let printToFile2 obj (file1 : System.IO.StreamWriter) =
file1.WriteLine(obj.ToString())
using (System.IO.File.CreateText("test.txt")) (printToFile2 "XYZ")
De using
functie en de use
binding zijn bijna gelijkwaardige manieren om hetzelfde te bereiken. Het using
trefwoord biedt meer controle over wanneer Dispose
wordt aangeroepen. Wanneer u dit gebruikt using
, Dispose
wordt aangeroepen aan het einde van de functie- of lambda-expressie. Wanneer u het use
trefwoord gebruikt, Dispose
wordt aangeroepen aan het einde van het codeblok. Over het algemeen moet u liever in plaats van de using
functie gebruikenuse
.