使用statement和try-catch() - 最后重复?

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所有者?与我的朋友的讨论指出了不是的答案.(我也在本论坛的使用部分阅读了一些主题,其中有一些非常好的知识).

Jon*_*n B 7

我的偏好是保留using语句并将其包装在try/catch中.外部try/catch将捕获您需要注意的任何异常,同时忽略Dispose().如果你稍后重构它以将try/catch移动到其他地方(比如在调用函数中),这还有一个额外的好处就是保护你自己.

关于IDisposable的问题:任何人都可以出于任何理由实现这一点.没有技术理由将其限制为非托管资源.(不论它是否应该在被限制在非托管资源,你的代码是一个不同的问题).


Joe*_*orn 7

如果你真的想要处理一些异常,你可以自己实现这个模式.就个人而言,我仍然觉得在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扩展到支持CatchFinally阻止.由于他们已经对代码进行了转换,因此这似乎不会增加额外的复杂性.