在try-catch块中使用块作为IDisposable是否有任何问题
本文关键字:是否 IDisposable 任何 问题 try-catch | 更新日期: 2023-09-27 18:27:15
MSDN建议将实现IDisposable
的类的任何实例化放入using
块中。或者,如果它在try-catch
块内被实例化,则Finally
中的Dispose
。
像这样在try-catch
块中使用using
块有什么问题吗?
try
{
using (Foo bar = new Foo())
{
bar.doStuff();
}
}
catch (Exception e)
{
//vomit e
}
当然,我可以在Finally
块中调用Dispose
,但我是编程新手,我只是想知道这样做是否切实可行,或者是否有人会打我的后脑勺,对我大喊我是Doing-It-Wrong™
。
或者更确切地说,我更感兴趣的是知道如果是这样,为什么会出错。
不,看起来很好。您的bar实例将在您进入catch块之前被丢弃。
这是…卷筒。。。绝对好。
唯一的问题是,您不应该使用catch (Exception)
,而是捕捉您感兴趣的特定错误(即使这只是一个示例),但这与using
无关。事实上,将using
放在try
块之外的唯一原因是,您希望继续对bar
执行与失败代码无关的操作——否则,保持尽可能小的范围通常是个好主意。
还好,但您失去了对可能导致异常的对象的访问权限
捕获一般异常不被认为是的好做法
Foo bar = null;
try
{
bar = new Foo();
bar.doStuff();
}
catch (IndexOutOfRangeException e)
{
//vomit e
Debug.WriteLine(e.msg);
if(bar == null)
Debug.WriteLine("bar = new Foo() failed ");
else
Debug.WriteLine("bar fail ID = " + bar.ID);
}
catch (Exception e)
{
// ...
// unless you are going to handle it gracefully you should rethrow it
}
finally
{
if(bar != null) bar.Dispose();
}
您的示例代码是多余的。Using()
文件规定:
形式的使用声明
using (ResourceType resource = expression)
语句对应于两个可能的展开式之一。当ResourceType是值类型时,扩展为
{
ResourceType resource = expression;
try {
statement;
}
finally {
((IDisposable)resource).Dispose();
}
}
否则,当ResourceType是引用类型时,扩展为
{
ResourceType resource = expression;
try {
statement;
}
finally {
if (resource != null) ((IDisposable)resource).Dispose();
}
}
在任一扩展中,嵌入语句中的资源变量都是只读的。
你的代码最终会看起来像:
try
{
Foo bar = new Foo()
try
{
bar.doStuff();
}
finally
{
if (bar != null) ((IDisposable)bar).Dispose();
}
}
catch (Exception e)
{
//vomit e
}
两个try语句没有真正的理由。这不是错误的代码,只是在多个try语句的上下文中是多余的。您的问题似乎是关于对象的Disposing
。在这种情况下,它是多余的。如果您还担心对象构造函数抛出异常,那么显然需要这样做。
在这样的try-catch块中使用using块有什么问题吗?
不,我一直在写你的例子。
当然,我可以在Finally块中调用Dispose,
在某种程度上,构造函数必须在try/catch之外调用,否则当您到达最终块时,变量将超出范围
有效:
var foo = new bar();
try
{
}
finally
{
foo.Dispose();
}
无效:
try
{
var foo = new bar();
}
finally
{
foo.Dispose();
}
不,这很好,但如果您想在catch
期间访问bar
,则需要一个内部try catch
:
try
{
using (Foo bar = new Foo())
{
try
{
bar.doStuff();
}
catch (Exception e)
{
//vomit e, with bar available.
}
}
}
catch (Exception e)
{
//vomit e, relating to a problem during creation of Foo.
}
或者,正如评论中所建议的,将内部块因素化为一种新方法。