.net - 为什么我不能在对象成员中使用一次性对象?

标签 .net f# idisposable

我不想将 StreamWriter 参数添加到 Write-To-File 过程,但是当我尝试使用一次性 StreamWriter 时,我得到:

An unhandled exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll

Additional information: Cannot write to a closed TextWriter.

代码:

let fileLogger = {
    new IFlog with
        member i.FLog level format =
            use file = LogFile()
            Printf.kfprintf 
                (fun f -> 
                    fprintfn file "[%s][%A] " 
                            <| level.ToString()
                            <| DateTime.Now
                    ) file (format)

所以当我两次调用 FLog 方法时,我得到了这个。

我可以像这样使用它:member i.FLog file level format 并在顶层控制一次性对象,但我失去了所有抽象。

有什么方法可以使用这样的一次性元素吗?或者我如何更改架构以避免将一次性参数传递给此函数?

日志文件是:

let mutable LogFileName = "F.log"
let LogFile() =
    match File.Exists(LogFileName) with
    | false -> File.CreateText(LogFileName)
    | true  -> File.AppendText(LogFileName)

最佳答案

你得到异常是因为你传递给 Printf.kfprintf 的函数被编译为一个闭包,它捕获对你的 file 变量的引用——即你的TextWriter 实例。一旦 Printf.kfprintf 返回,file 就超出范围;编译器发现它没有在其他任何地方使用,因此插入一些代码来调用 TextWriter 上的 Dispose() 方法。当您调用 FLog 方法返回的闭包时,file 已被释放,因此会引发异常。

使用一些代码可以更容易地进行可视化。这就是 F# 编译器编译 FLog 方法的方式:

member i.FLog level format =
    try
        let file = LogFile()
        Printf.kfprintf 
            (fun f -> 
                fprintfn file "[%s][%A] " 
                        <| level.ToString()
                        <| DateTime.Now
                ) file (format)
    finally
        if file <> null then file.Dispose ()

您可以通过使 FLog 的声明类型实现 IDisposable 并将 file 值作为类的一部分而不是声明来解决此问题它在方法中。当调用声明类型的 Dispose() 方法时,它应该只调用 file.Dispose()。你仍然需要注意不要在你处理完实例后使用你用 FLog 创建的任何闭包,否则你最终会得到与你现在看到的相同的异常.

关于.net - 为什么我不能在对象成员中使用一次性对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16234364/

相关文章:

f# - 将 "unit"作为类型参数传递给 F# 中的泛型类

xamarin - 如何从 Xamarin Android C# 项目调用返回字符串选项的 PCL 中的 F# 方法?

c# - Windows Phone 8 应用程序中的 ListView

c# - 考虑使用 MONO-TOUCH 编码时需要建议

f# - 如何为参数集定义合适的数据结构

c# - 使用 'using' 语句声明对象以备后用

c# - 正确的处理方式 : object not disposed along all exception paths

c# - 什么时候不调用 dispose 方法?

c# - Rhino Mocks 接收参数,修改它并返回?

c# - 有一个与类(class)同名的成员是不是不好的风格?