30

注意:这不是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 设置条件比必须自己编写测试更方便一些,但它并不能真正让你做任何新的事情。”

在向我正确解释之前,这是我的假设!

4

6 回答 6

4

至于任何现有的连接错误。以下问题处理异常过滤器。用户没有明确声明他们希望它们在执行时成为一个实际的过滤器,但恕我直言,这是逻辑所暗示的。

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 语句之间的区别。最近它似乎更多地出现在人们的脑海中,所以也许它会成为未来版本的语言。

于 2009-03-07T20:22:33.160 回答
2

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

要真正回答您的问题,您需要来自 Anders Hejlsberg 或参加原始设计会议的人员的回复。下次面试C# 设计团队时,您可以尝试看看是否可以让第 9 频道的面试官问到它。

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

我认为 postmoterm 诊断场景强烈支持以语言提供对异常过滤器的访问。但是,当时可能尚未阐明这些情况。此外,这些场景确实需要适当的工具支持,这在 V1 中肯定不可用。最后,添加这个我们没有考虑的功能可能会有很大的负面影响。

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

于 2009-03-07T06:07:08.927 回答
1

我也不相信 Java 有过滤器选项。猜测如果是这样,我们也会在 C# 中看到一个。鉴于 VB 团队从一张白纸开始,VB.net 可能有一个机会。

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

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

于 2009-03-07T18:00:12.237 回答
0

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

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

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

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

于 2009-03-02T17:29:30.077 回答
0

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

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

因此,除非我误解了某些东西,否则拥有语言支持的异常过滤器并没有很大的好处。

于 2009-03-03T08:01:58.417 回答
0

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

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

我真的很想在 C# 和 vb 中看到的一个功能,它需要使用异常过滤器来实现,但不需要直接公开它们,它将是Exception一个块的可选参数finallynull如果没有发生未捕获的异常,则此参数将是;否则它将持有有问题的例外。这将允许程序在发生异常时想要做某事但实际上并没有“处理”它的情况。在大多数情况下,该Exception参数不会用于除检查之外的任何事情null(这意味着该功能将等同于公开fault块),但它会在清理期间发生异常的情况下提供优势。目前,如果在一个过程中发生异常finally块,有必要要么扼杀finally-block 异常或覆盖预先存在的异常。让finally块代码可以使用较早的异常将使其能够包装或记录它。

于 2012-02-21T22:02:21.367 回答