笔记:这不是 杰夫问题的重复.

这个问题问:“等效吗?”我知道没有,我想知道为什么!

我之所以问这个问题,是因为我才刚刚明白它的重要性,而这个结论对我来说似乎很奇怪。

微软企业库的异常处理块建议我们使用这种模式:

catch (Exception x)
{
    if (ExceptionPolicy.HandleException(x, ExceptionPolicies.MyPolicy))
        throw;

    // recover from x somehow
}

该策略是在 XML 文件中定义的,因此这意味着如果客户遇到问题,我们可以修改策略来协助追踪(或者可能掩盖)问题,以便为他们提供快速解决方案,直到我们正确处理为止- 这可能涉及与第三方争论,这一切都是谁的错。

这基本上是对一个简单事实的承认,即在实际应用程序中,如果没有这样的工具,异常类型的数量及其“可恢复性”状态实际上是不可能管理的。

与此同时,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: 成立 Eric Gunnerson 的一篇有趣的旧博客文章, ,前 C# 团队成员:

“是的,能够在渔获量上施加条件要比必须自己编写测试要方便,但这并不能真正使您能够做任何新事物。”

这与我的假设相同,直到有人向我正确解释为止!

有帮助吗?

解决方案

至于任何现有的连接错误。以下问题涉及异常过滤器。用户没有明确声明他们希望它们成为执行时意义上的实际过滤器,但恕我直言,逻辑暗示了这一点。

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=401668

不过,除了这个问题之外,我找不到或知道没有与您正在寻找的内容相关的问题。我认为最好有一个单独的问题明确指出需要 VB.Net 样式异常过滤器。

如果您已经做了一些尽职调查来寻找现有的问题,我不会太担心引入重复的问题。如果存在欺骗行为,Mads 会相应地欺骗它,并将您链接到主要请求。

至于从 C# 团队获得官方回复的部分,当您 1) 提交连接错误或 2) 因主要错误而被欺骗时,您可能会得到这一信息。我真的怀疑现在是否有官方的理由/理由。

这是我的 猜测 关于这个问题:我的猜测是,这个功能根本就不在最初的 C# 1.0 功能集中,并且从那时起就没有足够的需求将其纳入该语言中。C# 和 VB 团队在每个发布周期开始时花费大量时间对语言功能进行排名。我们必须做一些 非常 有时很难进行切割。如果没有足够的需求,某个功能进入该语言的机会就很小。

直到最近,我敢打赌,您很难找到十分之一的人理解 VB.Net 的 Try/When 与在 C# catch 块中使用普通旧式 if 语句之间的区别。最近它似乎更受人们关注,所以也许它会成为该语言的未来版本。

其他提示

使用 异常过滤注入 可能比使用委托解决方法更简单。

要真正回答您的问题,您需要安德斯·海尔斯伯格(Anders Hejlsberg)或参加原始设计会议的人的答复。你可以尝试看看下次是否能被第九频道的采访者问到 C#设计团队接受采访.

我猜想,当做出最初的决定时,异常过滤器被视为一种不必要的复杂化,可能弊大于利。在这次采访中,您当然可以看到对于不支持检查异常的决定,人们希望对未经证实的功能保持“沉默”: 检查异常的麻烦.

我认为后期诊断场景强烈主张提供对语言中异常过滤器的访问。然而,当时可能还没有阐明这些场景。此外,这些场景确实需要适当的工具支持,而这在 V1 中肯定不可用。最后,我们没有考虑添加此功能可能会带来很大的负面影响。

如果没有连接错误,您应该输入一个并鼓励其他人投票。[我建议请求访问 CLR 功能,而不是尝试设计它如何适应该语言。]

我也不相信 Java 有过滤器选项。猜测如果确实如此,我们也会在 C# 中看到它。鉴于 VB 团队从头开始,VB.net 很可能有一个偶然。

在 C# 的未来版本中获得此选项可能对您有利的一件事是 Microsoft 的既定目标,即在 C# 和 VB.net 的未来版本中保持语言功能之间的平等。我将在此基础上提出我的论点。

http://www.chriseargle.com/post/2009/01/Parity-Between-Languages.aspx

关于第一个问题,如果有公开声明,那么它很可能会放在网络上的某个地方,在这种情况下,谷歌应该会发现一些东西(如果存在的话)。

如果它是直接发送给 C# 团队的电子邮件,那么它很可能处于 NDA 之下,因此无论如何都无法发布。

对于第二个问题,Microsoft Connect 上有一个搜索功能,他们会在输入新建议之前提示您使用该功能。如果你找不到它,那么很可能根本就没有。

我的建议是提出建议,然后进行推广,让其他人参与进来。

据我了解,在重新抛出时,内部函数中的finally处理程序被执行,这就是给你带来问题的原因。

但是,假设您有一个异常过滤器,它可以传递异常而不实际重新抛出异常。您仍然必须在某个地方以某种方式处理它,并且您将在那里遇到相同类型的问题(最终效果)。

因此,除非我误解了某些内容,否则使用语言支持的异常过滤器不会带来很大的好处。

我可以想到 C# 中缺少异常过滤的至少两个原因

  1. 允许异常过滤器可能会鼓励程序员在第一次异常处理期间做一些当时不安全的事情,即使它们可以在“catch”或“finally”中安全地完成。例如,如果“try”块中的代码获取锁并在持有锁时抛出异常,则该锁将在外部异常过滤器执行期间被持有,但将在外部“catch”或“finally”之前释放“块已运行。另外,至少在我上次检查时,异常过滤器中发生的异常但未被捕获的异常被默默地抑制了——这是一种丑陋的情况。
  2. C# 的实现者的愿景是让他们的语言“与框架无关”。如果 C# 支持 .net 首次通过异常过滤,则使用该功能的程序可能无法在以不同方式处理异常的框架上使用。这与 C# 禁止程序重写“Object.Finalize()”的原因相同。虽然围绕“Object.Finalize()”的推理是有缺陷的(正确使用析构函数需要使用其他特定于平台的方法,因此要求“Object.Finalize()”使用析构函数语法除了 t77o 鼓励编写有缺陷的软件)对于异常过滤器的推理确实有一定道理。另一方面,处理该问题的正确方法是公开一些与异常过滤器相关的功能,即使不直接公开异常过滤器也是如此。

我非常希望在 C# 和 vb 中看到一个功能,它需要使用异常过滤器来实现,但不需要直接公开它们,这将是一个可选功能 Exception 参数为 finally 堵塞。这个参数将是 null 如果没有发生未捕获的异常;否则它将保留有问题的例外。这将允许程序在发生异常时想要执行某些操作,但实际上并不“处理”它的情况。在大多数情况下, Exception 除了检查之外,参数不会用于任何其他用途 null (意味着该功能相当于暴露 fault 块),但在清理期间发生异常的情况下它会提供优势。目前,如果在执行期间发生异常 finally 阻止,有必要要么扼杀 finally- 阻止异常或覆盖先前存在的异常。将较早的例外情况提供给 finally 块代码将使其能够包装或记录它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top