我不想将 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/