【问题标题】:proper exception handling in VB.NETVB.NET 中的正确异常处理
【发布时间】:2013-07-24 12:46:26
【问题描述】:

我一直在寻找我的问题的答案,但我找不到太多,所以我在这里发帖,希望更有经验的开发人员可以启发我。在 sub 中构造异常处理的正确方法是什么?我应该将我的 Try、Catch、End Try 包裹在我的整个代码块中,还是可以在我的子代码中包裹一个 Try、Catch、End Try,然后在另一块代码中包裹 Try、Catch、End Try在同一个潜艇?这是我要问的一个例子:

这样更好吗?:(选项 1)

Try
        'check if user has selected a file
        If ListBoxPrePublish.SelectedItems.Count = 0 Then
            MessageBox.Show("Please select a file to delete.")
            Exit Sub
        End If

        'check if user has selected a Memo to publish, if so, move file to Publish folder; if user hasn't selected a Memo, move to next If statement
        If ListBoxPrePublish.SelectedItem.Contains("-M.xls") Then
            Dim resultMemo = MessageBox.Show("Are you sure you want to delete this Memo?", "", MessageBoxButtons.YesNo)
            If resultMemo = DialogResult.Yes Then
                Dim filePath As String = "W:\TOM\ERIC\Award_Letters\Excel pre_publish\"
                Dim movePath As String = "W:\TOM\ERIC\Award_Letters\Publish\"
                Dim filenm As String = ListBoxPrePublish.SelectedItem
                Dim FileToMove = filePath & filenm
                Dim MoveToLocation = movePath & filenm
                'move the file
                System.IO.File.Move(FileToMove, MoveToLocation)
                ListBoxPublished.Items.Add(ListBoxPrePublish.SelectedItem)
                ListBoxPrePublish.Items.Remove(ListBoxPrePublish.SelectedItem)
                Exit Sub
            Else
                Exit Sub
            End If
        End If



        'ask user if they're sure they want to publish selected file and corresponding files...remember, only if the selected item is not a Memo
        Dim result = MessageBox.Show("This action will publish all corresponding files for the selected student except for Memos. Memos must be deleted individually. Do you want to continue?", "", MessageBoxButtons.YesNo)
        If result = DialogResult.No Then
            Exit Sub
        Else

            If result = DialogResult.Yes Then
                'find ID for student in unapprovd accounting file, move the record to the Deleted Today file, delete record from unapproved accounting file
                Dim UnapprovedAcctFile As String = "W:\TOM\ERIC\Award_Letters\Accounting Files\Unapproved\" & StatVar.xlApp.Sheets("New Calculator Input").Range("D30").Value & ".xlsx"
                Dim ApprovedAcctFile As String = "W:\TOM\ERIC\Award_Letters\Accounting Files\Approved\" & StatVar.xlApp.Sheets("New Calculator Input").Range("D30").Value & " Import" & ".xlsx"
                Dim searchString As String = StatVar.xlApp.Sheets("Cross Checking").Range("J6").Text 'this is the ID that will be searched for in the accounting file
                Dim rng

                'make sure accounting file for school exists
                If Not IO.File.Exists(UnapprovedAcctFile) Then
                    MessageBox.Show("Could not locate the accounting file for this school. Please contact an administrator for assistance.")
                    Exit Sub
                End If

                'open accounting file and check if it's read only, if so, another user is editing it so close it and tell the user to try again in a few seconds, if it's not read only, see next comment
                StatVar.xlWBUnapprovedAcctFile = StatVar.xlApp.Workbooks.Open(UnapprovedAcctFile)
                If StatVar.xlApp.ActiveWorkbook.ReadOnly = True Then 'check if file is read only, if so close it and exit sub
                    StatVar.xlApp.ActiveWorkbook.Close(False)
                    MessageBox.Show("The system is busy. Please try again in a few seconds.")
                    Exit Sub
                End If

                'search unapproved accounting file for ID (SSN-award year example: 555555555-13) - use searchString variable above
                rng = StatVar.xlApp.ActiveWorkbook.Sheets("Sheet1").Range("BD2:BD30002").Find(searchString, , Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlWhole, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, False)
                'if searchString is found
                If rng IsNot Nothing Then
                    rng.EntireRow.Select() 'select the row searchString was found in
                    'check if approved accounting file for this school exists, if not, create it
                    If Not IO.File.Exists(ApprovedAcctFile) Then
                        StatVar.xlApp.Workbooks.Add()
                        StatVar.xlApp.ActiveWorkbook.SaveAs(ApprovedAcctFile)
                        StatVar.xlApp.ActiveWorkbook.Close(True)
                    End If
                    StatVar.xlWBApprovedAcctFile = StatVar.xlApp.Workbooks.Open(ApprovedAcctFile) 'open the Approved file
                    If StatVar.xlApp.ActiveWorkbook.ReadOnly = True Then 'check if the Approved file is read only, if so, close it and exit sub because it needs to be writable
                        StatVar.xlApp.ActiveWorkbook.Close(False) 'close the Approved file, don't save changes
                        StatVar.xlApp.ActiveWorkbook.Close(False) 'close unapproved accounting file, don't save changes
                        MessageBox.Show("The system is busy. Please try again in a few seconds.")
                        Exit Sub
                    End If
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.Columns("AV").NumberFormat = "@" 'format column AV of the Approved file as text so "13/14" remains formatted correctly
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.Rows("1:1").Insert(Excel.XlInsertShiftDirection.xlShiftDown) 'insert a row at the top of the Approved file
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.Rows("1:1").Value = rng.EntireRow.Value 'set the 1st row of the Approved file equal to the row selected earlier in the unapproved accounting file
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.UsedRange.RemoveDuplicates(Columns:=(56)) 'search column 56 in Approved file for duplicates and remove entire row if a duplicate ID is found
                    rng.EntireRow.Delete() 'delete row the searchString was found in from the unapproved accounting file
                    StatVar.xlApp.ActiveWorkbook.Close(True) 'close the Approved file, save changes
                    StatVar.xlApp.ActiveWorkbook.Close(True) 'close unapproved accounting file, save changes
                    'MessageBox.Show("Eureka!")
                Else
                    'if searchString is not found, close unapproved accounting file, inform user and exit sub
                    StatVar.xlApp.ActiveWorkbook.Close(False)
                    MessageBox.Show("Could not locate this record on the accounting file. Your files were not deleted.")
                    Exit Sub
                End If

                'move selected file and corresponding non-Memo files to Publish folder
                Dim filePath As String = "W:\TOM\ERIC\Award_Letters\Excel pre_publish\"
                Dim movePath As String = "W:\TOM\ERIC\Award_Letters\Publish\"
                Dim filenm As String

                'check if each item in listbox contains the string extracted from the selected item via Excel formula; listbox select event sends the filename to Excel and a formula extracts the string to find in each listbox item...look for this string
                For Each c In ListBoxPrePublish.Items
                    If c.ToString.Contains(StatVar.xlApp.Sheets("Cross Checking").Range("H6").Text) Then
                        'make sure the current listbox item in this loop is not a Memo, if it's not, move it
                        If Not c.ToString.Contains("-M.xls") Then
                            filenm = c
                            Dim FileToMove = filePath & filenm
                            Dim MoveToLocation = movePath & filenm
                            System.IO.File.Move(FileToMove, MoveToLocation)
                            ListBoxPublished.Items.Add(c) 'add files files that are being published to the published files listbox
                        End If
                    End If
                Next

                'refresh prepublish list, if user has a school selected, REMOVE all list items that don't contain the school code being generated via VLOOKUP in Excel using the school name from comboboxschool; look for this string in the loop surrounded with "-"
                Call ListFiles()
                If ComboBoxSchool.Text <> "" Then
                    For i As Integer = ListBoxPrePublish.Items.Count - 1 To 0 Step -1
                        'if current loop item does not contain the school code for the selected school, remove the item from the listbox
                        If Not ListBoxPrePublish.Items(i).Contains("-" & StatVar.xlApp.Sheets("Cross Checking").Range("E3").Text & "-") Then
                            ListBoxPrePublish.Items.RemoveAt(i)
                        End If
                    Next
                End If
                'refresh deleted files listbox
                Call ListDeletedTodayFiles()

            End If
        End If
    Catch exc As Exception
        MessageBox.Show("Unable to publish the selected file. Please verify this file or any of its corresponding files are not open by you or another user. If the problem persists, contact an administrator for assistance." & vbNewLine & vbNewLine & "Error: " & exc.Message)
    End Try

还是这样更好?:(选项 2)

 Try
        'check if user has selected a file
        If ListBoxPrePublish.SelectedItems.Count = 0 Then
            MessageBox.Show("Please select a file to delete.")
            Exit Sub
        End If

        'check if user has selected a Memo to publish, if so, move file to Publish folder; if user hasn't selected a Memo, move to next If statement
        If ListBoxPrePublish.SelectedItem.Contains("-M.xls") Then
            Dim resultMemo = MessageBox.Show("Are you sure you want to delete this Memo?", "", MessageBoxButtons.YesNo)
            If resultMemo = DialogResult.Yes Then
                Dim filePath As String = "W:\TOM\ERIC\Award_Letters\Excel pre_publish\"
                Dim movePath As String = "W:\TOM\ERIC\Award_Letters\Publish\"
                Dim filenm As String = ListBoxPrePublish.SelectedItem
                Dim FileToMove = filePath & filenm
                Dim MoveToLocation = movePath & filenm
                'move the file
                System.IO.File.Move(FileToMove, MoveToLocation)
                ListBoxPublished.Items.Add(ListBoxPrePublish.SelectedItem)
                ListBoxPrePublish.Items.Remove(ListBoxPrePublish.SelectedItem)
                Exit Sub
            Else
                Exit Sub
            End If
        End If
    Catch exc As Exception
        MessageBox.Show("An error occured and the selected file was not published. Please contact an administrator if the problem continues." & vbNewLine & vbNewLine & "Error: " & exc.Message)
    End Try

    Try
        'ask user if they're sure they want to publish selected file and corresponding files...remember, only if the selected item is not a Memo
        Dim result = MessageBox.Show("This action will publish all corresponding files for the selected student except for Memos. Memos must be deleted individually. Do you want to continue?", "", MessageBoxButtons.YesNo)
        If result = DialogResult.No Then
            Exit Sub
        Else

            If result = DialogResult.Yes Then
                'find ID for student in unapprovd accounting file, move the record to the Deleted Today file, delete record from unapproved accounting file
                Dim UnapprovedAcctFile As String = "W:\TOM\ERIC\Award_Letters\Accounting Files\Unapproved\" & StatVar.xlApp.Sheets("New Calculator Input").Range("D30").Value & ".xlsx"
                Dim ApprovedAcctFile As String = "W:\TOM\ERIC\Award_Letters\Accounting Files\Approved\" & StatVar.xlApp.Sheets("New Calculator Input").Range("D30").Value & " Import" & ".xlsx"
                Dim searchString As String = StatVar.xlApp.Sheets("Cross Checking").Range("J6").Text 'this is the ID that will be searched for in the accounting file
                Dim rng

                'make sure accounting file for school exists
                If Not IO.File.Exists(UnapprovedAcctFile) Then
                    MessageBox.Show("Could not locate the accounting file for this school. Please contact an administrator for assistance.")
                    Exit Sub
                End If

                'open accounting file and check if it's read only, if so, another user is editing it so close it and tell the user to try again in a few seconds, if it's not read only, see next comment
                StatVar.xlWBUnapprovedAcctFile = StatVar.xlApp.Workbooks.Open(UnapprovedAcctFile)
                If StatVar.xlApp.ActiveWorkbook.ReadOnly = True Then 'check if file is read only, if so close it and exit sub
                    StatVar.xlApp.ActiveWorkbook.Close(False)
                    MessageBox.Show("The system is busy. Please try again in a few seconds.")
                    Exit Sub
                End If

                'search unapproved accounting file for ID (SSN-award year example: 555555555-13) - use searchString variable above
                rng = StatVar.xlApp.ActiveWorkbook.Sheets("Sheet1").Range("BD2:BD30002").Find(searchString, , Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlWhole, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, False)
                'if searchString is found
                If rng IsNot Nothing Then
                    rng.EntireRow.Select() 'select the row searchString was found in
                    'check if approved accounting file for this school exists, if not, create it
                    If Not IO.File.Exists(ApprovedAcctFile) Then
                        StatVar.xlApp.Workbooks.Add()
                        StatVar.xlApp.ActiveWorkbook.SaveAs(ApprovedAcctFile)
                        StatVar.xlApp.ActiveWorkbook.Close(True)
                    End If
                    StatVar.xlWBApprovedAcctFile = StatVar.xlApp.Workbooks.Open(ApprovedAcctFile) 'open the Approved file
                    If StatVar.xlApp.ActiveWorkbook.ReadOnly = True Then 'check if the Approved file is read only, if so, close it and exit sub because it needs to be writable
                        StatVar.xlApp.ActiveWorkbook.Close(False) 'close the Approved file, don't save changes
                        StatVar.xlApp.ActiveWorkbook.Close(False) 'close unapproved accounting file, don't save changes
                        MessageBox.Show("The system is busy. Please try again in a few seconds.")
                        Exit Sub
                    End If
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.Columns("AV").NumberFormat = "@" 'format column AV of the Approved file as text so "13/14" remains formatted correctly
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.Rows("1:1").Insert(Excel.XlInsertShiftDirection.xlShiftDown) 'insert a row at the top of the Approved file
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.Rows("1:1").Value = rng.EntireRow.Value 'set the 1st row of the Approved file equal to the row selected earlier in the unapproved accounting file
                    StatVar.xlApp.ActiveWorkbook.ActiveSheet.UsedRange.RemoveDuplicates(Columns:=(56)) 'search column 56 in Approved file for duplicates and remove entire row if a duplicate ID is found
                    rng.EntireRow.Delete() 'delete row the searchString was found in from the unapproved accounting file
                    StatVar.xlApp.ActiveWorkbook.Close(True) 'close the Approved file, save changes
                    StatVar.xlApp.ActiveWorkbook.Close(True) 'close unapproved accounting file, save changes
                    'MessageBox.Show("Eureka!")
                Else
                    'if searchString is not found, close unapproved accounting file, inform user and exit sub
                    StatVar.xlApp.ActiveWorkbook.Close(False)
                    MessageBox.Show("Could not locate this record on the accounting file. Your files were not deleted.")
                    Exit Sub
                End If

                'move selected file and corresponding non-Memo files to Publish folder
                Dim filePath As String = "W:\TOM\ERIC\Award_Letters\Excel pre_publish\"
                Dim movePath As String = "W:\TOM\ERIC\Award_Letters\Publish\"
                Dim filenm As String

                'check if each item in listbox contains the string extracted from the selected item via Excel formula; listbox select event sends the filename to Excel and a formula extracts the string to find in each listbox item...look for this string
                For Each c In ListBoxPrePublish.Items
                    If c.ToString.Contains(StatVar.xlApp.Sheets("Cross Checking").Range("H6").Text) Then
                        'make sure the current listbox item in this loop is not a Memo, if it's not, move it
                        If Not c.ToString.Contains("-M.xls") Then
                            filenm = c
                            Dim FileToMove = filePath & filenm
                            Dim MoveToLocation = movePath & filenm
                            System.IO.File.Move(FileToMove, MoveToLocation)
                            ListBoxPublished.Items.Add(c) 'add files files that are being published to the published files listbox
                        End If
                    End If
                Next

                'refresh prepublish list, if user has a school selected, REMOVE all list items that don't contain the school code being generated via VLOOKUP in Excel using the school name from comboboxschool; look for this string in the loop surrounded with "-"
                Call ListFiles()
                If ComboBoxSchool.Text <> "" Then
                    For i As Integer = ListBoxPrePublish.Items.Count - 1 To 0 Step -1
                        'if current loop item does not contain the school code for the selected school, remove the item from the listbox
                        If Not ListBoxPrePublish.Items(i).Contains("-" & StatVar.xlApp.Sheets("Cross Checking").Range("E3").Text & "-") Then
                            ListBoxPrePublish.Items.RemoveAt(i)
                        End If
                    Next
                End If
                'refresh deleted files listbox
                Call ListDeletedTodayFiles()

            End If
        End If
    Catch exc As Exception
        MessageBox.Show("Unable to publish the selected file. Please verify this file or any of its corresponding files are not open by you or another user. If the problem persists, contact an administrator for assistance." & vbNewLine & vbNewLine & "Error: " & exc.Message)
    End Try

这些方法中的任何一种是否比另一种更好?还是由我决定,取决于我对我的程序做了什么?很想听听对此的不同意见。

【问题讨论】:

  • 将 try/catch 包裹在大块代码周围被广泛认为是一种非常糟糕的做法。
  • 尝试/捕获块很昂贵。使它们的范围尽可能小。这也使您能够提供更精确的错误记录,从而简化调试。
  • 您介意详细说明原因吗?我不是在质疑你,只是想了解“为什么”。如果你能给我指出一个好的链接,我会阅读它,我无法找到关于这个主题的很多有用的文献
  • 你的方法做的很多,125行代码就是一团糟。
  • 这不是我的问题。发展是一个草率的过程。一旦我确定我已经覆盖了所有的基础,一切都会被整理。我宁愿不必在解决问题的同时点击我的项目。那是多余的。在这一点上,我不确定我会在整个项目中重用哪些代码,哪些不会,所以在我确定一切都已经确定之前,什么都不会被分离出来。

标签: vb.net exception-handling


【解决方案1】:

将您的 Try-Catch-Finally 块包裹在较小的代码部分周围,这样您将有更好的机会更快地找到错误,并有可能从异常中恢复并继续执行部分逻辑。在您的一个异常处理程序场景中,如果发生任何错误,则不会执行其余逻辑,这也使得查找错误发生的位置变得更加困难。这带来了最终的建议,让你的方法做得更少;需要滚动多个页面的方法做得太多,很难理解和维护,而且几乎肯定不可能在其他任何地方重用。

您也不应该只使用基本的Exception,因为这是一种包罗万象的异常类型,无法深入了解实际发生的更具体的异常类型。

【讨论】:

  • “在您的一个异常处理程序场景中,如果发生任何错误,则不会执行其余的逻辑”......酷,这正是我想要在这里发生的事情。谢谢
【解决方案2】:

明智的做法是将 try catch 包裹在较小的代码块中,具体取决于您要执行的错误处理深度。 Microsoft 有一个关于错误处理最佳实践的页面:

MSDN Best Practices for Handling Exceptions

【讨论】:

    【解决方案3】:

    您应该尝试以全局方式处理异常,例如在应用程序事件级别。如果您希望其他代码继续运行,您应该使块尽可能窄。捕获异常会影响性能。

    【讨论】:

      【解决方案4】:

      看起来比实际更糟糕的问题,因为您可以将该方法分解为几个小方法

      这样看

      如果您有 a、b 和 c,并且您想计算出 a/b 和 a/c,并且您将所有这些都放在一个 try catch 中,以获取 div 的零异常,那么您需要做更多的工作才能弄清楚不管 b 还是 c 是坏人,两个 try catch 块你就知道了。

      是的,我知道这不是何时使用异常的最佳示例,但您的问题的答案是否取决于您希望如何处理代码段中的已知异常。

      在上面,如果您对句柄“b 或 c 为零”表示满意,那么解决方案就是一个块。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-07
        • 2021-05-22
        • 2012-04-06
        • 2016-04-21
        • 2016-08-21
        • 1970-01-01
        • 2016-12-30
        • 1970-01-01
        相关资源
        最近更新 更多