2010-12-13 3 views
9

Supponiamo che io creo una chiusura su una risorsa come uno StreamWriter:F #: smaltimento delle risorse che si trovano all'interno di una chiusura?

let currentdir = Directory.GetCurrentDirectory() 
let testfile = sprintf "%s\\%s" currentdir "closuretest.txt" 

let getwriter() = 
    let writer = new StreamWriter(testfile, false) 
    (fun() -> writer.Write "test") 

C'è un modo per chiudere lo StreamWriter quando ho finito con la chiusura? O devo sostituire la chiusura con un oggetto wrapper che ha un metodo Write() e un metodo Dispose()? (Questo è ovviamente un esempio banalizzato.) Grazie a tutti.

risposta

7

Sì, è necessario sostituire la chiusura con un oggetto IDisposable con un metodo e un Dispose(). (In alternativa, restituire una tupla di chiusure, il secondo dei quali chiama Close() o roba del genere, e lasciare al chiamante del genere.)

(Mentre si è in esso, System.IO.Path.Combine() dovrebbe essere utilizzato, invece di incollare insieme i nomi dei file . con formattazione di stringhe)

+0

Grazie mille Brian per la rapida risposta. Il materiale F # disponibile sembra parlare di chiusure e gestione delle risorse, ma non i due insieme. – FSharpN00b

3

volte faccio:

let getwriter() = 
    let writer = new StreamWriter(testfile, false) 
    (fun() -> 
    use writer = writer 
    writer.Write "test") 
+0

La ringrazio molto per la sua risposta Dr. Harrop. Sembra che mantenga il lavoro di aprire il file fuori dalla chiusura, ma che comunque chiuda il file alla chiusura della chiusura. Lo userò in futuro. – FSharpN00b

1

IDisposable è di circa deterministicamente, risorse cioè esplicitamente rilascio. Pertanto, se la chiusura non fornisce in qualche modo una funzionalità di smaltimento autonoma, la risorsa non può più essere rilasciata in modo deterministico.

Come ha sottolineato Brian, questo può essere più o meno esplicito, sebbene l'implementazione di IDisposable sia preferibile in quanto use + IDisposable si occupa automaticamente del rilascio di risorse in caso di eccezioni.

Tuttavia, a volte è sufficiente nascondere completamente la risorsa monouso e ottenere una chiusura di ciò che deve essere fatto.

let getWriter body = 
    use writer = new StreamWriter(testfile, false) 
    body(writer) 

// ... 

getWriter (fun writer -> writer.Write "test") 
+0

Grazie mille per la risposta Dario. Da quello che ho sentito, una chiusura è rappresentata solo come un altro oggetto .NET. Mi chiedo se ad un certo punto avremo un modo per aggiungere il codice finalize/dispose ad esso. – FSharpN00b