C# using语句是否只处理它创建的第一个变量?
假设我有一个一次性对象C# using语句是否只处理它创建的第一个变量?,c#,idisposable,using,C#,Idisposable,Using,假设我有一个一次性对象MyDisposable,它将另一个一次性对象作为构造函数参数 using(MyDisposable myDisposable= new MyDisposable(new AnotherDisposable())) { //whatever } 假设myDisposable不在它的dispose方法中处理另一个disposable 这是否仅正确处置我的一次性产品?或者它也会处理另一个可丢弃的?它不会“处理”任何东西。它调用其中使用的对象的Dispose方法。你的
MyDisposable
,它将另一个一次性对象作为构造函数参数
using(MyDisposable myDisposable= new MyDisposable(new AnotherDisposable()))
{
//whatever
}
假设
myDisposable
不在它的dispose方法中处理另一个disposable
这是否仅正确处置我的一次性产品?或者它也会处理另一个可丢弃的?它不会“处理”任何东西。它调用其中使用的对象的
Dispose
方法。你的工作是清理其他东西。。可能通过调用另一个对象上的dispose来实现。为什么不嵌套它们
using(var outer = new AnotherDisposable())
{
using(var inner = new MyDisposable(outer))
{
//whatever
}
}
现在至少你可以确定它们会被正确地处理掉。
使用
相当于
MyDisposable myDisposable = new MyDisposable(new AnotherDisposable());
try
{
//whatever
}
finally
{
if (myDisposable != null)
myDisposable.Dispose();
}
因此,如果
myDisposable
没有调用另一个disposable,using
也不会调用它。在这种情况下,它不会处理另一个disposable。有两种解决方案
首先,您通常会执行以下操作:
using (AnotherDisposable anotherDisposable = new AnotherDisposable())
using (MyDisposable myDisposable= new MyDisposable(anotherDisposable))
{
}
然而,还有另一条路要走。当一个类获取一次性对象时,它自己会处理它所获取的对象,这是很正常的。例如,包装流的StreamReader
将处理它包装的流。这意味着您选择的构造将起作用。您可以在MyDisposable
中实现相同的功能,然后您所采用的方法就可以了。C#的using语句提供了一个在对象上调用Dispose的语法快捷方式
使用try/finally块实现IDisposable。例如:
using (FileStream fs = new FileStream ("myFile.txt", FileMode.Open))
{
// ... Write to the file ...
}
编译器将其转换为:
FileStream fs=newfilestream(“myFile.txt”,FileMode.Open)
finally块确保即使在出现异常时也调用Dispose方法
抛出,1或代码提前退出块
因此,使用单个块只能确保单个一次性对象得到处置。另一方面,您可以使用嵌套的using语句。像
using (myDisposable d = new myDisposable())
{
using(Disposable2 d2 = new Disposable2())
{
// do something and dispose...
}
}
这将转换为
try
{
// work around for myDisposable
try
{
// work around for Disposable2
}
finally
{
if (d2 != null)
((IDisposable)d2 ).Dispose();
}
}
finally
{
if (d!= null)
((IDisposable)d).Dispose();
}
您仅使用
语句初始化了中的一个一次性变量。另一个可丢弃的
嵌套对象是通过正常初始化创建的,而不是通过使用
。因此,只有您使用using
语句创建的myDisposable
变量才会被它自动处理。是的,它会处理,它不会处理另一个disposable
,您需要手动管理另一个一次性的应该在MyDisposable
实现上处理,因为它在那里使用。问题是使用double-using使FxCop显示CA2202:对象不应该多次处理,但这是因为在我使用的真实案例中,我知道innerDisposable由outerDisposable处理,所以我猜测这是否可以通过+1完成,这是处理清理的最佳方式。值得注意的是,甚至不需要第二组括号。这可以归结为您的格式设置偏好,但您可以使用语句直接堆叠在彼此的顶部,并使用相同的括号表示范围。这实际上是在回答我的问题时使用(MyDisposable MyDisposable=new MyDisposable(new AnotherDisposable()){…}
模式只有在MyDisposable
的构造函数不仅承诺MyDisposable.Dispose
将处理传递到构造函数中的对象,而且如果在构造函数本身期间发生任何异常,将立即处理传递的项时才是安全的,这是一种比它困难得多的模式应该是正确的。
try
{
// work around for myDisposable
try
{
// work around for Disposable2
}
finally
{
if (d2 != null)
((IDisposable)d2 ).Dispose();
}
}
finally
{
if (d!= null)
((IDisposable)d).Dispose();
}