This post contains two inter-related questions that have cleaning up resources in common. I have read this SO post, along with several others on Microsoft's sites trying to determine what is a managed versus an unmanaged resource. Based on what I've read the following code block uses .Net managed resources. This is from non-DLL F# library.
namespace Toa.csv_lib
open System
open System.Threading
open System.Collections.Generic
open System.Linq
open System.Text
open System.Threading.Tasks
open System.IO
open Microsoft.VisualBasic.FileIO
[<AutoOpen>]
module csv_lib =
let initCsvLib fn delim =
let csvFileH = new TextFieldParser(fn:string)
csvFileH.TextFieldType = FieldType.Delimited |> ignore
csvFileH.SetDelimiters(delim) |> ignore
csvFileH
let readCsvLibLine csvFileH =
(csvFileH:TextFieldParser).ReadFields()
let retCsvData csvFileH =
let csvData = new List<string[]>()
if not (csvFileH:TextFieldParser).EndOfData then
let column_headings = readCsvLibLine csvFileH
csvData.Add(column_headings) |> ignore
let read_rest_of_csv() =
csvData.Add(readCsvLibLine csvFileH) |> ignore
not (csvFileH:TextFieldParser).EndOfData
while read_rest_of_csv() do ignore None
csvData // Last expression is returned.
Even though I believe csvFileH
and csvData
to be managed resources, I was wondering is there an inverse to [<AutoOpen>]
and does there need to be one? This would be a directive that would allow a library to would free up all the resources created in [<AutoOpen>]
.
I could restructure this code to have using
around the csvFileH
, because that handle that is needed only to read in a .csv file. But given a List<string[]> csvData
type is returned, is that still considered a managed resource that will be garbage-disposed when the application shuts down.
All that [<AutoOpen>]
does is expose the contents of the module without an open
statement. That's it. It's not running any code, it's just exposing something automatically which would need to be exposed manually.
In your case though when you're referencing this module, you're not actually executing anything. initCsvLib
is a pure function that takes two args and returns an instance of csvFileH
. There is no initialization code being run here. If you had for example
module Foo =
let expensiveThing = ExpensiveThing()
let myFn arg1 arg2 =
// This isn't run until the function myFn is called.
let expensiveThing = ExpensiveThing()
// ...
Then you may have a problem on your hands. In that case though you'd have to recall that modules are really static classes and basically follow the same rules as static classes do in C# (thinking about when static constructors are run) and go from there.
But if you get to that point you should instead be asking yourself why you have such an expensive operation in a constructor in the first place...