【问题标题】:error handling continue point after error caught and handled错误捕获和处理后的错误处理继续点
【发布时间】:2016-02-16 10:46:46
【问题描述】:

我有一个正在升级的大型程序 vb.net。我正在编写错误处理程序,以便即使出现异常(文件不存在等)程序也可以继续运行。但是我对所有的错误处理感到困惑。

如果我有多个相互调用的方法,并且我在顶级方法周围放置了一个try catch,那么在处理异常后程序将继续运行的点在哪里?

例如:

public Sub Main()
    Dim a As Integer
    Try
        If (Foo()) Then
            a = Boo()
        End If
    Catch
    End Try
    'Is a 10 here???
End Sub

public Function Foo() As Boolean
    Line1
    Line2
    Line3
    return True
End Function

Public Function Boo() As Int
    Line4
    Line5
    Line6
    return 10
End Function

在这种情况下无论如何都会调用Boo(),例如a 总是= 10? - 即使lines 1-6上出现异常?

【问题讨论】:

    标签: vb.net error-handling try-catch


    【解决方案1】:

    不,在您的示例中,如果Foo 抛出异常,则将立即进入Catch 块。 Boo 函数将被调用,a 的值将被设置。

    即使您的 Main 函数没有使用任何 Try/Catch 块,这也是正确的:

    Public Sub Main()
        Dim a As Integer
        If (Foo()) Then
            a = Boo()
        End If
    End Sub
    

    Boo() 只会被调用,a 只会被设置为其结果,如果Foo 抛出异常。如果Foo 抛出,运行时将搜索合适的异常处理程序。找不到,而且这是顶级方法,您将遇到未处理的异常,然后导致应用程序终止。

    这就是为什么不应该将异常用于流量控制,而只能用于实际的异常情况。

    only 将您希望抛出的东西放入 Try 块中,onlyCatch 块用于您知道如何处理的异常。我还建议尽可能在声明中初始化变量。一些虚构的代码作为逻辑上应该如何工作的示例:

    Public Sub Main()
        Dim val As Integer = 0    ' 0 is our "default" value
    
        ' Don't need a Try here, this won't throw an exception.
        ' It will just return an empty string if they canceled.
        Dim fileName As String = AskUserForFileName()
    
        ' See if they canceled...
        If (fileName <> String.Empty)
            Try
               ' Now we need a Try block, because we're going to do
               ' stuff that might throw an exception.
               Dim file As File = OpenFile(fileName)
    
               ' Execution won't get here if OpenFile() threw an exception, so
               ' at this point, we know that the file was opened successfully,
               ' so we'll try to read our value from it.
               val = ReadDataFromFile(file)
    
               ' Again, execution won't get here if ReadDataFromFile() threw
               ' an exception, so we know that the data was read out successfully
               ' and our val variable has been updated.
            Catch ex As FileNotFoundException
               MessageBox.Show("Could not find the specified file.")
            Catch ex As System.IO.IOException
               MessageBox.Show("Could not read from the specified file--check it is valid.")
            End Try
        End If
    
        ' Our variable val will now contain the value read from the file,
        ' if that whole business was successful. Otherwise, it will
        ' contain the default value of 0 that we set at the top.
    End Sub
    

    在实际代码中,您还可以广泛使用Using blocks 来处理实现IDisposable 接口的任何对象的自动 清理,以防引发异常。修改我们上面的例子,假设我编写的File 类实现了IDisposable

    Public Sub Main()
        Dim val As Integer = 0    ' 0 is our "default" value
    
        ' Don't need a Try here, this won't throw an exception.
        ' It will just return an empty string if they canceled.
        Dim fileName As String = AskUserForFileName()
    
        ' See if they canceled...
        If (fileName <> String.Empty)
            Try
               ' Now we need a Try block, because we're going to do
               ' stuff that might throw an exception.
               Using file As File = OpenFile(fileName)
                   ' Execution won't get here if OpenFile() threw an exception, so
                   ' at this point, we know that the file was opened successfully,
                   ' so we'll try to read our value from it.
                   val = ReadDataFromFile(file)
    
                   ' Again, execution won't get here if ReadDataFromFile() threw
                   ' an exception, so we know that the data was read out successfully
                   ' and our val variable has been updated.
               End Using  ' make sure file always gets closed properly
            Catch ex As FileNotFoundException
               MessageBox.Show("Could not find the specified file.")
            Catch ex As System.IO.IOException
               MessageBox.Show("Could not read from the specified file--check it is valid.")
            End Try
        End If
    
        ' Our variable val will now contain the value read from the file,
        ' if that whole business was successful. Otherwise, it will
        ' contain the default value of 0 that we set at the top.
    End Sub
    

    【讨论】:

    • 很好的答案,但只有一个问题?如果您没有为您的catch 语句指定异常,那么不是所有异常都在那个catch 中得到处理吗?即我在我的例子中有什么?
    • @Jabba 是的,他们有。这真的不是一个好主意。您应该只处理您知道如何处理的异常。吞下您从未预料到的异常是一个坏主意,因为它可以隐藏错误。例如,如果您遇到 OutOfMemory 异常怎么办?你打算怎么处理?技巧问题:你不能!但如果你吞下它,它会隐藏一个错误。最好让你不知道如何处理的异常冒泡。确实,它们会使你的程序崩溃,但无论如何你都会崩溃,因为有些事情搞砸了,而且你不知道如何修复它。
    • 感谢额外的链接。在我正在升级的这个程序中(我从其他人那里继承了它),大多数返回值的函数都有错误处理,因此如果发生错误,函数会返回一个默认值(大多数方法都有自己的try catch整个事情。)这也是不好的做法吗?如果不是,什么是可接受的等价物?
    • @Jabba 很难说没有看到代码。一般来说,最好不要破坏有效的东西。但是看到一堆散布在整个代码中的 try/catch 块是不寻常的,而且在我看来有点代码味道。真的有那么多您期望并能够处理的异常吗?如果没有,你不应该抓住他们。文件处理是典型的例子,你必须处理由于竞争条件而导致的异常。对于 GUI 代码、用户输入等,几乎不需要异常,只需使用条件检查输入即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多