2

这篇文章包含两个相互关联的问题,它们具有共同的清理资源。我已经阅读了这篇 SO帖子,以及 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.

尽管我相信csvFileH并被csvData管理资源,但我想知道是否存在相反的情况[<AutoOpen>],是否需要有一个?这将是一个指令,允许库释放在[<AutoOpen>].

我可以重新构建这段代码,使其具有using,csvFileH因为只需要读取 .csv 文件的句柄。但是如果List<string[]> csvData返回了一个类型,它仍然被认为是一个托管资源,当应用程序关闭时将被垃圾处理。

4

1 回答 1

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# 中的静态类相同的规则(考虑何时运行静态构造函数)并从那里开始。

但是如果你到了那个地步,你应该问自己为什么首先在构造函数中进行如此昂贵的操作......

于 2016-09-12T17:46:54.193 回答