[英]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.