为什么我不能使用对象成员可支配的对象? [英] Why I can not use disposable objects in object members?
问题描述
我不希望添加的StreamWriter
参数写入到文件的程序,但是当我试图用一次性的StreamWriter那里我得到工作:
键入System.ObjectDisposedException的未处理的异常mscorlib.dll中发生
其他信息:无法写入一个封闭的TextWriter。
code:
让fileLogger = {
新IFlog
会员i.FLog级别的格式=
使用文件=日志文件()
Printf.kfprintf
(有趣的F - >
fprintfn文件[%s]的[%A]
< | level.ToString()
< | DateTime.Now
)文件(格式)
所以当我打电话鞭打方法两次我得到这一点。
我可以用它类似这样:成员i.FLog文件级别的格式
和控制支配对象的顶层,但后来我失去了所有的抽象
有没有一些方法来使用这样的一次性的对象?或者我如何改变结构来避免将一次性参数到这个功能呢?
日志文件是:
让可变LOGFILENAME =F.log的
让日志文件()=
比赛File.Exists(LOGFILENAME)与
|假 - > File.CreateText(LOGFILENAME)
|真 - > File.AppendText(LOGFILENAME)
你得到的异常,因为你传递给 Printf.kfprintf
被编译为一个封闭的功能捕捉引用您的文件
变量 - 例如,你的的TextWriter
实例。一旦 Printf.kfprintf
返回,文件
超出范围;编译器看到,它不是其他任何地方使用,因此插入了一些code调用上的的TextWriter $的
的Dispose()
方法C $ C>。到时候你调用由鞭打返回关闭
方法,文件
已被设置成该异常。
这是一个比较容易直观一些code。这是怎样的F#编译器编译鞭打
方法:
成员i.FLog级别的格式=
尝试
让文件=日志文件()
Printf.kfprintf
(有趣的F - >
fprintfn文件[%s]的[%A]
< | level.ToString()
< | DateTime.Now
)文件(格式)
最后
如果文件<> null,则file.Dispose()
您可以通过让鞭打
实施的IDisposable
的声明类型,并且使<$ C $解决这个问题C>文件值类的一部分,而不是方法中声明它。当声明类型的的Dispose()
方法被调用,它应该只需要调用 file.Dispose()
。你还需要注意不要用你与鞭打产生的任何封闭
您已经处理后的实例,虽然,否则你会最终与同例外,你现在看到的。
I don't want to add StreamWriter
parameter to Write-To-File procedure but when I'm trying to work with disposable StreamWriter there I'm getting:
An unhandled exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll
Additional information: Cannot write to a closed TextWriter.
code:
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)
so when I call FLog method twice I get this.
I can use it alike this : member i.FLog file level format
and control disposable object on top level but then I lose all the abstraction.
Is there some way to use disposable objects like that? Or how can I change architecture to avoid passing disposable parameter into this function?
LogFile is :
let mutable LogFileName = "F.log"
let LogFile() =
match File.Exists(LogFileName) with
| false -> File.CreateText(LogFileName)
| true -> File.AppendText(LogFileName)
You're getting the exception because the function you pass to Printf.kfprintf
is compiled as a closure which captures a reference to your file
variable -- i.e., your TextWriter
instance. Once Printf.kfprintf
returns, file
goes out of scope; the compiler sees that it is not used anywhere else and thus inserts some code to call the Dispose()
method on the TextWriter
. By the time you call the closure returned by the FLog
method, file
has already been disposed so the exception is raised.
It's a little easier to visualize with some code. This is how the F# compiler compiles the FLog
method:
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 ()
You could fix this by having the declaring type of FLog
implement IDisposable
, and making the file
value part of the class instead of declaring it within the method. When the declaring type's Dispose()
method is called, it should just call file.Dispose()
. You'll still need to take care not to use any closures you've created with FLog
after you've disposed the instance though, or you'll end up with the same exception you're seeing now.
这篇关于为什么我不能使用对象成员可支配的对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!