在 F# 中正确处理流

Properly disposing a stream in F#

以下代码在读取文件时抛出 ObjectDisposedException。在枚举整个序列之前,BinaryReader 似乎超出了范围。在不泄漏 reader 的情况下安全地进行此调用的正确方法是什么?我宁愿不必在顶级代码中进行流管理——理想情况下,它是隐藏在给定文件路径的地方。

在此代码中,Edge.ReadBinary 执行从二进制流中反序列化 Edge 的明显任务。在我的代码中,该文件夹做了一些更复杂的事情,但为了便于阅读,我在这里对其进行了简化。

let rec readEdges (br:BinaryReader) =
    seq {
        match Edge.ReadBinary br with
        | None -> yield! Seq.empty  
        | Some(e) -> yield e; yield! readEdges br        
    }

let readBinaryEdges fn =
    use br=new BinaryReader(File.OpenRead(fn))
    readEdges br

let sampled=readBinaryEdges fn |> Seq.fold (fun result l -> l::result) list.Empty 

正如 iljdarn 的评论中所指出的,将 use 放在序列表达式中可以解决此问题。这是有效的,因为序列表达式构建器为 use 关键字定义了自己的语义,以支持在适当的时间进行处置。因此,如果您将函数更改为

let readBinaryEdges fn =
    seq { use br = new BinaryReader(File.OpenRead(fn))
          yield! readEdges br }

reader 将与序列一起处理。