Gur*_*epS 15 c# using try-catch-finally
using(...)语句是try {} finally {}的语法糖.
但是,如果我有一个如下所示的使用声明:
using (FileStream fs = File.Open(path))
{
}
Run Code Online (Sandbox Code Playgroud)
现在我想要捕获打开此文件可能导致的异常(这是相当高风险的代码,因为它可能因环境而失败),但是如果我在里面写try-catch会不会重复?当代码被编译为IL时,我假设当代码被JIT时,重复将被删除?
但是,我想要捕获打开文件可能导致的异常(所以我应该将try-catch包装在using语句的作用域之外),以及我在using块中做的任何异常,所以我应该添加try-catch在街区内.
这似乎是我在CLR可能在里面做了很多重复.CLR是否添加了catch子句?
我的同事认为使用声明是混乱的(但这是因为由于我需要对它们进行硬编码,所以单行很长,因为我需要非常快速地更改它们并且无法访问代码库的其他部分).说同事不使用using语句,但是using语句和try-finally/try-catch-finally之间是否存在任何功能差异?我确实看到了一个这样的案例,其中WCF服务有一个关于使用finally和返回值的一个鲜为人知的角落案例(最后的事情).解决方案是使用检查块.在C#中有这样的东西吗?
另一方面,是否所有类型都实现了非托管资源的IDisposale所有者?与我的朋友的讨论指出了不是的答案.(我也在本论坛的使用部分阅读了一些主题,其中有一些非常好的知识).
我的偏好是保留using语句并将其包装在try/catch中.外部try/catch将捕获您需要注意的任何异常,同时忽略Dispose().如果你稍后重构它以将try/catch移动到其他地方(比如在调用函数中),这还有一个额外的好处就是保护你自己.
关于IDisposable的问题:任何人都可以出于任何理由实现这一点.没有技术理由将其限制为非托管资源.(不论它是否应该在被限制在非托管资源,你的代码是一个不同的问题).
如果你真的想要处理一些异常,你可以自己实现这个模式.就个人而言,我仍然觉得在try/catch块中包装使用更简单(更重要的是,更清楚).
但如果你自己做,请确保你做对了.该Using块还会创建一个匿名范围块,以便您的变量更快地符合收集条件..Dispose()在Using块结束时调用的方法仅清除非托管资源,因此您的对象保留的任何内存可能会挂起一段时间.这不太可能是一个巨大的问题,但值得记住以防万一.
因此,要直接调整模式,您的代码需要看起来更像这样:
{
FileStream fs;
try
{
fs = File.Open(path);
}
catch (FileNotFoundException e) { /* ... */ }
catch (IOException e) { /* ... */ }
catch (Exception e) {/* ... */}
finally
{
if (fs != null) fs.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
就个人而言,我希望看到Using扩展到支持Catch和Finally阻止.由于他们已经对代码进行了转换,因此这似乎不会增加额外的复杂性.
| 归档时间: |
|
| 查看次数: |
12677 次 |
| 最近记录: |