F #: Утилизация ресурсов, которые находятся внутри замыкания? - PullRequest
9 голосов
/ 13 декабря 2010

Предположим, я создаю закрытие для ресурса, такого как StreamWriter:

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

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

Есть ли способ закрыть StreamWriter, когда я закончу с закрытием?Или мне нужно заменить замыкание объектом-оберткой, у которого есть метод Write () и метод Dispose ()?(Это, конечно, банальный пример.) Спасибо всем.

Ответы [ 3 ]

7 голосов
/ 13 декабря 2010

Да, вы должны заменить замыкание объектом IDisposable на метод и Dispose().(В качестве альтернативы, верните кортеж замыканий, второй из которых вызывает Close() или что-то в этом роде, и оставьте его вызывающей стороне вот так.)

(Пока вы это делаете, следует использовать System.IO.Path.Combine()вместо склеивания имен файлов с форматированием строк.)

3 голосов
/ 14 декабря 2010

Я иногда так и делаю:

let getwriter() =
  let writer = new StreamWriter(testfile, false)
  (fun() ->
    use writer = writer
    writer.Write "test")
1 голос
/ 14 декабря 2010

IDisposable - это примерно детерминистически , то есть явное освобождение ресурсов. Таким образом, если замыкание само по себе не обеспечивает функцию удаления, ресурс не может быть освобожден детерминистически больше.

Как отметил Брайан, это может быть более или менее явным, хотя реализация IDisposable предпочтительнее, так как use + IDisposable автоматически заботится об освобождении ресурсов в случае исключений.

Однако иногда бывает достаточно полностью скрыть одноразовый ресурс и получить информацию о том, что нужно сделать вместо этого.

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

// ...

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