是否有比嵌套“使用”更好的确定性处置模式?
在 C# 中,如果我想确定性地清理非托管资源,我可以使用“using”关键字。 但对于多个依赖对象,这最终会嵌套得越来越深:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
// use sr, and have everything cleaned up when done.
}
}
}
在 C++ 中,我习惯于使用析构函数来执行此操作:
{
FileStream fs("c:\file.txt", FileMode.Open);
BufferedStream bs(fs);
StreamReader sr(bs);
// use sr, and have everything cleaned up when done.
}
C# 中是否有更好的方法来执行此操作? 或者我是否陷入了多层嵌套?
In C#, if I want to deterministically clean up non-managed resources, I can use the "using" keyword. But for multiple dependent objects, this ends up nesting further and further:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (StreamReader sr = new StreamReader(bs))
{
// use sr, and have everything cleaned up when done.
}
}
}
In C++, I'm used to being able to use destructors to do it like this:
{
FileStream fs("c:\file.txt", FileMode.Open);
BufferedStream bs(fs);
StreamReader sr(bs);
// use sr, and have everything cleaned up when done.
}
Is there a better way in C# to do this? Or am I stuck with the multiple levels of nesting?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
using 语句是语法糖,可转换为:
您可以在对象上显式调用 Dispose,但它不会那么安全,因为如果其中一个抛出异常,则资源将无法正确释放。
The using statement is syntactic sugar that converts to:
You can explicitly call Dispose on your objects, but it won't be as safe, since if one of them throws an exception, the resources won't be freed properly.
对于此示例,我们假设您有:
c:\ 下名为 1.xml 的文件
名为 textBox1 的文本框,且多行属性设置为 ON。
for this example let us assume you have:
a file named 1.xml under c:\
a textbox named textBox1, with the multi-line properties set ON.
应该注意的是,通常当基于另一个流创建流时,新流将关闭传入的流。因此,为了进一步减少示例:
It should be noted that generally when creating stream based off another stream the new stream will close the one being passed in. So, to further reduce your example:
这使得代码行数增加了很多,但可读性有了明显的提高:
StreamWrapper 的定义如下:
通过一些努力,StreamWrapper 可以被重构为更通用和可重用。
This makes for a much larger net plus in lines of code, but a tangible gain in readability:
Where StreamWrapper is defined here:
With some effort, StreamWrapper could be refactored to be more generic and reusable.
您可以手动写出 .Dispose 调用,而不是嵌套 using 语句 - 但您几乎肯定会在某些时候错过一个。
运行 FxCop 或其他可以确保所有 IDisposable 实现类型实例都有 .Dispose() 调用的程序,或者处理嵌套。
Instead of nesting using statements, you can just write out the .Dispose calls manually - but you'll almost certainly miss one at some point.
Either run FxCop or something else that can make sure that all IDisposable-implementing type instances have a .Dispose() call, or deal with the nesting.
您可以省略花括号,例如:
或使用常规的 try finally 方法:
you can omit the curly braces, like:
or use the regular try finally approach:
我已经实现了像 Michael Meadows 之前的,但他的
StreamWrapper
代码没有考虑对成员变量调用的Dispose()
方法是否因某个原因引发异常或者,后续的 Dispose() 将不会被调用,并且资源可能会悬空。 更安全的工作方式是:I have implemented solutions like Michael Meadows's before, but his
StreamWrapper
code doesn't take into account if theDispose()
methods called on the member variables throw an exception for one reason or another, the subsequentDispose()
es will not be called and resources could dangle. The safer way for that one to work is:您可以将 using 语句放在左大括号之前,如下所示:
http ://blogs.msdn.com/ericgu/archive/2004/08/05/209267.aspx
You can put using statements together before the opening braces like so:
http://blogs.msdn.com/ericgu/archive/2004/08/05/209267.aspx
您可以使用此语法来压缩一些内容:
恕我直言,这是一种罕见的情况,不对所有块使用 { } 是有意义的。
You could use this syntax to condense things down a bit:
This is one of those rare occasions where not using { } for all blocks makes sense IMHO.
您不必嵌套多个 using:
在 .NET Core 中,有一个新的 using 语句,它允许您省去括号,并且处理发生在当前作用域的末尾:
You don't have to nest with multiple usings:
In .NET Core, there's a new using statement which allows you to dispense with the parentheses, and the disposal happens at the end of the current scope: