繁体   English   中英

VB.NET尝试使用多个Catch块捕获

[英]VB.NET Try Catch with multiple Catch blocks

这是一个非常奇怪的问题。 我们有一个包含多个Catch块的Try Catch。 第一个Catch块没有代码,只有注释。

Try
  'Some Code
Catch ex As ThreadAbortException
  'Do Nothing
Catch ex As Exception
  HandleException(ex)
End Try

如果抛出ThreadAbortException以外的异常,则会被第二个Catch捕获,如预期的那样。 但是,当在VS2010中单步执行代码时,ex对象在这种情况下是Nothing。 到目前为止,我们已经找到了两种“修复”此问题的方法。

修复1:重命名第一个异常变量。

Try
  'Some Code
Catch tex As ThreadAbortException
  'Do Nothing
Catch ex As Exception
  HandleException(ex)
End Try

修复2:将任何代码行添加到第一个Catch块。

Try
  'Some Code
Catch ex As ThreadAbortException
  Dim i As Integer = 1
Catch ex As Exception
  HandleException(ex)
End Try

在任何上述情况下,HandleException中的代码在运行时似乎仍能正常运行。 这是Visual Studio或调试器中的错误吗? 或者我们在这里遗漏了什么,上面第一段代码无效?

这一切都在.NET 4.0中完成。

Teejay有正确的答案。

但是,如果您的Catch块为空,则完全没有理由处理此异常。 你只是想阻止最后一个块捕获它。 可以使用您的方法 - 但是考虑到具有空的Catch块通常是不可接受的:异常应该被捕获,或者应该被正确处理; 静静地吞咽它们必须被视为一种虫子。 您的情况是此规则的一个例外,但因此需要在代码中记录,因为否则会使精心维护者感到困惑。

那么,VB对于这种情况有一个特殊的习惯用语:

Try
    ' …
Catch ex As Exception When Not TypeOf ex Is ThreadAbortException
    ' Only executed if `ex` isn’t a ThreadAbortException
End Try

这段代码根本不会捕获ThreadAbortException ,如果你不想处理它,这是正确的做法: 不能吞下ThreadAbortException所以即使你捕获它,它也会在Catch块的末尾重新抛出。

请注意,这与SysDragon使用常规If语句的答案根本不同,而此处的代码在Catch语句中使用特殊子句作为过滤器。

它似乎是一个VS'调试器错误。

证明

如果你写:

Try
    Throw New InvalidOperationException("MESSAGE")
Catch ex As ArgumentException
    'Do Nothing
Catch ex As Exception
    Debug.WriteLine(ex)
End Try

并且你看ex它在Quickwatch模式下评估为Nothing

在控制台中程序正确打印System.InvalidOperationException: MESSAGE

好的,让我详细说明......

看来你必须在每个捕获中都有一个“结果”。 如果您只是希望特定捕获不会发生任何事情,请不要包含它,或将其移动到代码中的其他位置。

Try
   'Some Code
Catch ex As ThreadAbortException
   'Do something(ex: HandleExceptionSub())
Catch ex As Exception
   HandleException(ex)
End Try

如果你“抓住”一个例外,你必须对它做一些事情。

编辑:

我还发现了这些信息,可以帮助您进一步了解try catch的工作方式:

多个捕获块

try块可以抛出多个异常,可以通过使用多个catch块来处理。 请记住,更专业的catch块应该在广义块之前出现。 否则编译器将显示编译错误。 多个捕获块

它不是调试器的“Bug”。 调试器旨在帮助您查找和处理所有异常。

编辑:似乎可以完全避免我在另一篇文章中读到的这个异常。 而且似乎最好避免异常,而不是不处理它。 处理ThreadAbortException

编辑:刚刚在try中找到了有关多个catch块的更多信息。 这是来自MSDN并声明永远不会到达空白catch块后的catch块... 尝试Catch Finally Statement进一步证明这不是一个bug,而是强制处理代码中所有异常的预期功能。

编辑:为了在评论中直接设置一些人,我创建了一个非常简单的测试程序,看看这确实是一个bug。 我的发现是捕获块完美地工作。 似乎遵循MSDN记录的创建具有多个Catch块的Try Catch的方式正如他们所说的那样工作。

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            if (textBox1.Text == "")
            {
                throw new ArgumentNullException("textBox1", "TextBox can not be empty");
            }
            else
            {
                MyString(textBox1.Text);
            }
        }
        catch (ArgumentNullException ex)
        {
            //nothing
        }
        catch (Exception ex)
        {
            MessageBox.Show("Test: " + ex.Message);
        }
    }

    private int MyString(string text)
    {
        return int.Parse(text);
    }

我创建了一个带有按钮和文本框的简单表单。 如果文本框为空,则抛出ArgumentNullException,并在“MyString”中将字符串解析为抛出“FormatException”的整数。 有一个空白的catch块,这不是处理“捕获”异常的正确方法确实有效。 所以据我所知,这不是一个错误。 显然我唯一同意Teejay和Konrad的意思是你不能使用try catch方法捕获和处理ThreadAbortException。 Konrad的解决方案是编写try catch的最佳方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM