这篇文章包含两个相互关联的问题,它们具有共同的清理资源。我已经阅读了SO post以及Microsoft网站上的其他一些文章,试图确定什么是托管资源还是非托管资源。根据我阅读的内容,以下代码块使用.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.

尽管我相信csvFileHcsvData是托管资源,但我想知道[<AutoOpen>]是否与之相反,是否需要一个?这将是一条指令,该指令将允许库释放[<AutoOpen>]中创建的所有资源。

我可以重新构造此代码,使using周围有csvFileH,因为仅在读取.csv文件时才需要该句柄。但是,如果返回List<string[]> csvData类型,则仍将其视为托管资源,该资源将在应用程序关闭时进行垃圾处理。

最佳答案

[<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#中静态类相同的规则(考虑何时运行静态构造函数),然后再去那里。

但是如果到了这一点,您应该问自己为什么首先要在构造函数中进行如此昂贵的操作...

10-08 13:42