问题标签 [finally]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - c#“finally”块,只在异常上运行
编辑:我查看了答案代码:他们都没有做我想要的(我已经检查过)。似乎没有办法在本机 c# 中做我想做的事。我想这不是一场灾难,只是一种耻辱,因为 .NET 确实支持它(见接受的答案)。
谢谢大家。
我有像这样的 c# 代码(测试框架的一部分,除非在调试器下运行,否则永远不会运行)谁指出它是为了避免实际捕获异常,因为这使得调试堆栈未展开部分中的代码非常痛苦。
他们是更好的方法吗?
对于未捕获的异常,解决方案的行为必须与调试器下的行为完全相同。它必须导致唯一的第一次机会异常,并且调试器在最初引发异常的点中断,而不是在 catch 块中。
具体来说,我需要未捕获异常的调试器来停止 MightThrow。
以下不起作用,因为它无法让调试器在正确的位置中断
这不起作用,因为它会丢失堆栈信息(并且还会在错误的位置中断)。
我知道在D中我可以使用scope(failure)
块
c# - 为什么 C# 不支持首次通过异常过滤?
注意:这不是Jeff 问题的重复。
那个问题问“是等价的吗?” 我知道没有,我想知道为什么!
我问的原因是我才刚刚清楚它的重要性,结论对我来说似乎很奇怪。
Microsoft 企业库的异常处理块建议我们使用这种模式:
该政策是在 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 设置条件比必须自己编写测试更方便一些,但它并不能真正让你做任何新的事情。”
在向我正确解释之前,这是我的假设!
c# - 为什么我的 finally 块在 C# 中不起作用?
我一直在帮助一位同事调试他们代码中的一些奇怪行为。以下示例说明了这一点:
这个样本返回了什么?
您会认为由于 finally 块,它返回“def”,但实际上它返回“abc”?我已经单步执行了代码并确认 finally 块实际上已被调用。
真正的答案是你不应该首先编写这样的代码,但我仍然对这种行为感到困惑。
编辑:根据一些答案澄清流程。
当您单步执行代码时,finally 在返回之前执行。
c# - try 语句中的问题
这是我用来设置 TCP 服务器的代码
如果你在同一个目的地调用 Bind,你会得到一个异常,因为端口已经在使用中,所以当我调用该函数两次时,我会得到那个异常。
问题 - 在 Catch{} 语句之后,即使我捕获了异常,代码仍继续遵循 finally{},为什么会发生这种情况?我希望它在消息框之后退出函数。我尝试使用“return”,但它仍然继续跟随 finally{} 块。
c# - C#最终执行时间
拿这个代码:
这给了我这个输出:
我的问题是:为什么未处理的异常文本出现在 finally 之前?在我看来,finally 应该在堆栈展开时被执行,甚至在我们知道这个异常未处理之前。注意对 Sleep() 的调用 - 这些发生在打印未处理的异常之后,就好像它正在执行以下操作一样:
- 未处理的异常文本/消息
- 最后阻塞。
- 终止申请
根据 C# 标准,§8.9.5,这种行为是错误的:
- 在当前函数成员中,检查包含抛出点的每个 try 语句。对于每个语句 S,从最里面的 try 语句开始,到最外面的 try 语句结束,评估以下步骤:
- 如果 S 的 try 块包含了抛出点,并且如果 S 有一个或多个 catch 子句,则按出现的顺序检查 catch 子句以找到合适的异常处理程序。指定异常类型或异常类型的基类型的第一个 catch 子句被视为匹配项。一般的 catch 子句(第 8.10 节)被认为是任何异常类型的匹配项。如果找到匹配的 catch 子句,则通过将控制转移到该 catch 子句的块来完成异常传播。
- 否则,如果 S 的 try 块或 catch 块包围了抛出点,并且如果 S 有 finally 块,则控制转移到 finally 块。如果 finally 块抛出另一个异常,则终止当前异常的处理。否则,当控制到达 finally 块的终点时,继续处理当前异常。
- 如果异常处理程序不在当前函数成员调用中,则终止函数成员调用。然后对函数成员的调用者重复上述步骤,并使用与调用函数成员的语句相对应的抛出点。
- 如果异常处理终止了当前线程中的所有函数成员调用,表明该线程没有异常处理程序,则该线程本身终止。这种终止的影响是实现定义的。
我哪里错了?(我有一些自定义控制台错误消息,这是在路上。轻微的,只是烦人,让我质疑语言......)
c# - 使用语句扩展的好奇 C#
我已经运行 ildasm 来发现:
生成与此等效的 IL 代码:
问题是为什么它会在finally中检查null?finally 块只有在 try 块被执行时才会被执行,而 try 块只有在 Simple 构造函数成功(即不抛出异常)时才会被执行,在这种情况下 simp 将是非空的。(如果有人担心在 Simple 构造函数和 try 块的开头之间可能会出现一些干预步骤,那么这确实是一个问题,因为可能会引发异常,从而完全阻止 finally 块的执行。)那么,到底为什么?
抛开(请)使用语句是否比 try-finally 更好的论点,我将 try-finally 块编写为:
exception - 尝试/最终忽略异常吗?
我有一种情况,无论发生什么情况,我都希望执行某些代码,但我还需要将异常传递到堆栈上以便稍后处理。是否如下:
p>会忽略任何异常,还是会将它们传递出去?我的测试似乎表明它们仍然可以通过,但我想确定我没有发疯。
编辑:我的问题不是关于最终何时以及是否会执行,而是关于异常是否仍会向上抛出,但现在已经回答了。
java - 最终好奇的Java未初始化变量
当我遇到一段有趣的代码时,我试图为我正在帮助的替代开源 JVM ( Avian ) 提出晦涩的测试用例,但我很惊讶它没有编译:
最明显的代码路径(我看到的唯一一个)是执行a = 1,“尝试”返回a(第一次),然后执行finally,它实际上返回a。但是,javac 抱怨“a”可能没有被初始化:
我能想到的唯一可能导致/允许不同代码路径的事情是,如果在尝试开始之后但在将值 1 分配给 a 之前发生模糊的运行时异常 - 类似于 OutOfMemoryError 或 StackOverflowException,但我想不出这些可能发生在代码中的这个地方的任何情况。
任何更熟悉 Java 标准细节的人都可以对此有所了解吗?这只是编译器保守的情况 - 因此拒绝编译原本有效的代码 - 还是这里发生了一些奇怪的事情?
c# - 最后尝试神秘
考虑,
示例代码输出“1”。但是在 finally 块中 i 的值更改为 3。为什么'i'的值没有改为3?
谢谢,