注意:这不是Jeff 问题的重复。
那个问题问“是等价的吗?” 我知道没有,我想知道为什么!
我问的原因是我才刚刚清楚它的重要性,结论对我来说似乎很奇怪。
Microsoft 企业库的异常处理块建议我们使用这种模式:
catch (Exception x)
{
if (ExceptionPolicy.HandleException(x, ExceptionPolicies.MyPolicy))
throw;
// recover from x somehow
}
该政策是在 XML 文件中定义的,这意味着如果客户有问题,我们可以修改政策以帮助追踪(或可能掩盖)问题,以便快速解决问题,直到我们妥善处理- 这可能涉及与第 3 方争论,这一切都是谁的错。
这基本上承认了一个简单的事实,即在实际应用程序中,如果没有这样的工具,几乎不可能管理异常类型的数量及其“可恢复性”状态。
与此同时,MS 的 CLR 团队表示这不是一个选项,事实证明这些人知道他们在说什么!问题是在catch
块运行之前,finally
嵌套在块内的任何块try
都将被执行。因此,这些finally
块可以执行以下任何操作:
- 无害地修改程序状态(呸,幸运)。
- 丢弃客户数据中的一些重要内容,因为程序状态被搞砸到了未知的程度。
- 伪装或破坏我们需要诊断问题的重要证据——尤其是当我们谈论对本机代码的调用时。
- 抛出另一个例外,增加了普遍的混乱和痛苦。
请注意,using
语句和 C++/CLI 析构函数是基于try
/构建的finally
,因此它们也会受到影响。
很明显,过滤异常的catch
/throw
模式并不好。真正需要的是一种通过策略过滤异常的方法,而不是实际捕获它们并因此触发finally
块的执行,除非我们找到一个告诉我们异常可以安全恢复的策略。
CLR 团队最近在博客中谈到了这一点:
结果是我们必须在 VB.NET 中编写一个辅助函数,以允许我们从 C# 访问这一重要功能。存在问题的重要线索是 BCL 中有执行此操作的代码。很多人都写过关于这样做的博客,但他们很少提到关于try
/finally
块的事情,这是杀手。
我想知道的是:
- 人们是否从 C# 团队收到了有关此主题的任何公开声明或直接电子邮件?
- 是否有任何现有的 Microsoft Connect 建议要求这样做?我听说过关于它们的谣言,但没有任何可能的关键词出现。
更新:如上所述,我已经在 Microsoft Connect 上进行了搜索,但没有找到任何东西。我也(毫不奇怪)谷歌搜索。我只发现有人解释他们为什么需要这个特性,或者指出它在 VB.NET 中的优点,或者徒劳地希望它会被添加到未来的 C# 版本中,或者解决它,以及大量误导性的建议. 但没有说明从所有当前版本的 C# 中省略它的理由。我询问现有 Connect 问题的原因是(a)我不会创建不必要的副本,并且(b)如果我必须创建一个,我可以告诉感兴趣的人。
更新 2:从C# 团队的前任Eric Gunnerson 那里找到一篇有趣的旧博客文章:
“是的,能够对 catch 设置条件比必须自己编写测试更方便一些,但它并不能真正让你做任何新的事情。”
在向我正确解释之前,这是我的假设!