这篇文章包含两个相互关联的问题,这些问题共同清理了资源。我已经阅读了这个SO post,以及微软网站上的其他几个人试图确定什么是托管资源和非托管资源。根据我读到的内容,以下代码块使用.Net托管资源。这是来自非DLL F#库。
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.
即使我认为csvFileH
和csvData
是托管资源,但我想知道是否存在与[<AutoOpen>]
的反转,是否需要有一个?这将是一个允许库释放[<AutoOpen>]
中创建的所有资源的指令。
我可以重新构造此代码,使using
周围有csvFileH
,因为只需读取.csv文件就需要该句柄。但是如果返回List<string[]> csvData
类型,那么它仍被视为托管资源,当应用程序关闭时,它将被垃圾处理。
答案 0 :(得分:8)
[<AutoOpen>]
所做的只是在没有open
语句的情况下公开模块的内容。就是这样。它没有运行任何代码,它只是自动暴露某些需要手动曝光的内容。
在您的情况下,虽然当您引用此模块时,您实际上并未执行任何操作。 initCsvLib
是一个纯函数,它接受两个args并返回csvFileH
的实例。这里没有运行初始化代码。如果你有例如
module Foo =
let expensiveThing = ExpensiveThing()
let myFn arg1 arg2 =
// This isn't run until the function myFn is called.
let expensiveThing = ExpensiveThing()
// ...
然后你可能手上有问题。在这种情况下,虽然您必须回忆起模块实际上是静态类,并且基本遵循与C#中静态类相同的规则(考虑何时运行静态构造函数)并从那里开始。
但是如果你达到这一点,你应该首先问问自己为什么你在构造函数中有这么昂贵的操作......