我理解“使用”的意思是保证调用对象的Dispose方法。但是如何处理“使用”语句中的异常呢?如果有异常,我需要在try catch中包装我的“using”语句。例如:
假设在使用参数
try
{
// Exception in using parameter
using (SqlConnection connection = new SqlConnection("LippertTheLeopard"))
{
connection.Open();
}
}
catch (Exception ex)
{
}
或使用范围内的例外
using (SqlConnection connection = new SqlConnection())
{
try
{
connection.Open();
}
catch (Exception ex)
{
}
}
似乎我已经需要使用try catch处理异常,也许我应该只处理对象的处理。在这种情况下,“使用”声明似乎并没有帮助我。如何使用“using”语句正确处理异常?是否有更好的方法来解决这个问题?
SqlConnection connection2 = null;
try
{
connection2 = new SqlConnection("z");
connection2.Open();
}
catch (Exception ex)
{
}
finally
{
IDisposable disp = connection2 as IDisposable;
if (disp != null)
{
disp.Dispose();
}
}
“使用”关键字语法可能会更加含糖......
这肯定会很高兴:
using (SqlConnection connection = new SqlConnection())
{
connection.Open();
}
catch(Exception ex)
{
// What went wrong? Well at least connection is Disposed
}
答案 0 :(得分:27)
因为你会在一个不相关的关键字中“隐藏”额外的功能。
但是你总是这样写的
using (...) try
{
}
catch (...)
{
}
这种方式代表你的意图 - 一个也是一个尝试的使用陈述
答案 1 :(得分:12)
using
与错误处理无关。它是“当你离开这个区块时调用Dispose”的简写。你的第二个代码示例是完全可以接受的......为什么搞乱哪些有效?
答案 2 :(得分:8)
using块只是try-finally块的语法糖。如果你需要一个catch子句,只需使用try-catch-finally:
SqlConnection connection;
try
{
connection = new SqlConnection();
connection.Open();
}
catch(Exception ex)
{
// handle
}
finally
{
if (connection != null)
{
connection.Dispose();
}
}
是的,这比你的理论“使用 - 捕获”更多的代码;我判断语言开发人员并不认为这是一个非常重要的问题,我不能说我曾经感受到它的损失。
答案 3 :(得分:5)
我有过这个有用的地方。但更常见的是,当我想要这样做时,事实证明问题出在我的设计中;我正试图在错误的地方处理异常。
相反,我需要允许它进入下一个级别 - 在调用此代码的函数中处理它,而不是在那里。
答案 4 :(得分:2)
一个有趣的想法,但它会让以下有点混乱:
using (SqlConnection connection = new SqlConnection())
using (SqlCommand cmd = new SqlCommand())
{
connection.Open();
}
catch(Exception ex)
{
// Is connection valid? Is cmd valid? how would you tell?
// if the ctor of either throw do I get here?
}
答案 5 :(得分:2)
我认为你在混淆问题。资源管理(即对象的处置)与异常处理完全分开。您在问题中描述的一对一映射只是一个非常特殊的情况。通常,异常处理不会在使用范围结束的同一位置发生。或者,您可能在使用块中有多个try-catch区域。或者......
答案 6 :(得分:0)
我建议您使用示例#1和#2组合。原因是你的using语句可以读取一个文件,例如,抛出一个异常(即File Not Found)。如果你没有捕获它,那么你有一个未处理的异常。将try catch块放在using块中只会捕获using语句执行后发生的异常。您的示例一和二的组合是最好的恕我直言。
答案 7 :(得分:0)
“using”语句的目的是确保在执行退出代码块时会发生某种类型的清理操作,无论该退出是通过直通,异常还是return
。当块通过任何这些方式退出时,它将在Dispose
的参数上调用using
。从某种意义上说,该块存在于为using
参数指定的任何内容的好处,并且通常情况下该事件将不关心该块被退出的原因。
有几个不寻常的案例可能对这些条款有所帮助;他们的附加效用水平远远低于首先使用using
所提供的水平(尽管可能比实施者认为适合提供的其他功能更好):
(1)对象的构造函数或工厂中有一个非常常见的模式,它封装了其他IDisposable
个对象;如果构造函数或工厂通过异常退出,则封装的对象应为Dispose
d,但如果它通过return
退出,则不应该。try
目前,此类行为必须通过catch
/ try
或finally
/ using
与旗帜相结合来实施,但如果存在任何变化,恕我直言Dispose
只会在通过异常退出时调用keep using
,或者是using
语句,它会使using
语句所使用的临时空间无效以保存对象需要处理(因为yield return
不能以标识符开头,这样的功能可能会以某种类似于finally
)的方式添加。
(2)在某些情况下,如果Exception
关键字扩展为接受null
参数,将会很有帮助;它会保留导致被保护条款退出的异常(如果有的话),或using
如果被保护的条款正常退出(通过返回或通过),并且interface IDisposeExOnly {void DisposeEx(Exception ex);}
块可以使用Interface IDisposeEx : IDisposable, IDisposableExOnly {}
和DisposeEx()
(在编译时,如果已实施则选择Dispose()
,否则为null
)。这可以允许基于事务的对象安全地支持自动提交(即,如果传入的异常为Dispose
则执行提交,或者如果非空则则执行回滚),并且还允许在以下情况下改进日志记录Dispose
由于受保护的子句中的问题而失败(正确的事情是{{1}}抛出一个异常,该异常封装了调用它时挂起的异常,以及发生的异常因此,目前还没有干净的方法来做到这一点。)
我不知道微软是否会添加这些功能;第一部分和第二部分将完全在语言层面处理。第二部分的后半部分将处于框架层面。