在過去ASP時代,程式碼中只有On Error可用來捕捉或處理錯誤,而ASP.NET中,除了On Error可用之外,還可以利用Try …End Try來進行錯誤處理。
『Try…End Try』這個新玩意兒,看起來好像很有學問的樣子,其實用起來相當的簡單,基本的指令架構如下:
Try [ tryStatements ] [ Catch [ exception [ As type ] ] [ When expression ] [ catchStatements ] ] [ Exit Try ] ... [ Finally [ finallyStatements ] ] End Try |
上面是『Try…Catch…Finally』在.NET Framework中完整的定義,對於程式設計師,它的內涵就是:
Try 可能發生錯誤的程式 [ Catch [ exception [ As type ] ] [ When expression ] 發生錯誤時,要執行的指令 [ Exit Try ]若下了Exit Try 指令,則跳出Try…End Try結構 [ Catch [ exception [ As type ] ] [ When expression ] Catch 可以有很多個,程式會依照 When 後面的expression來決定執行哪一個Catch敘述 [ Finally 只要一進入Try敘述中,不管有沒有錯誤或從Try敘述中的哪一部份離開都執行的程式 End Try |
底下是實例:
Public Sub TryExample() Dim x As Integer = 5 '定義兩個整數 Dim y As Integer = 0 Try ' 進入Try結構,從這裡開始捕捉錯誤 x =x/ y '發生錯誤→除以零 Catch ex As Exception When y = 0 '當錯誤產生時,若Y=0就執行這段錯誤處理程式 resp(“發生錯誤,除以零!!!”) Finally Beep() '只要進入錯誤處理程序,完成後就Beep一聲 End Try End Sub |
這樣的錯誤處理結構,比起過去的On Error 看似複雜許多,但是程式設計上卻較結構化,程式設計師不再需要因為On Error Goto敘述Goto來Goto去,造成閱讀和撰寫的困擾而傷腦筋。
我們看一個實例,請開啟一個Web From,在上面佈置兩個TextBox、一個Button和一個Label:
並在Run這個按鈕的Click事件裡,撰寫底下的程式碼:
完整範例請參考Chapter02\TryError\Default.aspx |
0001: Private Sub Run_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Run.Click 0002: Dim n1, n2 As Single 0003: 0004: Try '開始Try...End Try 迴圈 0005: '這裡是可能發生錯誤的(想要捕捉錯誤的)敘述 0006: n1 = Me.NumA.Text / Me.NumB.Text 0007: n2 = Me.NumB.Text / Me.NumA.Text 0008: 0009: Catch ex As Exception When Me.NumB.Text = 0 0010: '當發生錯誤,且NumB.Text=0時執行... 0011: Me.result.Text += "<br>-->發生錯誤(B):" & ex.Message 0012: 0013: Catch ex As Exception When Me.NumA.Text = 0 0014: '當發生錯誤,且NumA.Text=0時執行... 0015: Me.result.Text += "<br>-->發生錯誤(A):" & ex.Message 0016: 0017: Catch ex As Exception 0018: '當發生錯誤時執行... 0019: Me.result.Text += "<br>-->發生錯誤:" & ex.Message 0020: 0021: Finally '只要進入錯誤迴圈即執行 0022: Me.result.Text += "<br>-->執行過 Finally..." 0023: 0024: End Try '開始Try...End Try 迴圈 0025: 0026: Me.result.Text += "<br>-->n1 (A/B):" & n1 0027: Me.result.Text += "<br>-->n2 (B/A):" & n2 0028: End Sub |
從第4到24行是一段完整的Try…End Try迴圈,第5到7行是我們想要捕捉的錯誤可能發生的位置(我們判斷有可能使用者輸入0,導致除以零錯誤),當錯誤發生在這裡時,就會被Try…End Try迴圈捕捉。
9到11、13到15、17到19都是當錯誤發生時,要處理的對應程序,我們看第9行的例子:
Catch ex As Exception When Me.NumB.Text = 0 |
當錯誤發生,且『Me.NumB.Text = 0』時,則執行9到11行的程式。(很有趣的事情是,在.NET Framework上,這段程式永遠不會被執行,因為居然沒有除以零錯誤!很怪?待會解釋…)
如果發生錯誤時,不是第9和13行的『Catch ex As Exception When Me.NumB.Text = 0』和『Catch ex As Exception When Me.NumA.Text = 0』,則會處理第17行『Catch ex As Exception』以後的敘述。
『Exception』傳回錯誤處理程序的物件,ex.Message 傳回錯誤訊息,而ex.Source則傳回發生錯誤的程式碼來源。
我們實際看執行例子,首先,在欄位中輸入7和3,這個例子比較沒有爭議,計算結果直接顯示出來,整個過程中沒有發生錯誤,因此不會有捕捉錯誤的訊息,但是請注意,依舊會執行到程式中的『Finally』部分:
但是當我們把A和B改成底下這樣,錯誤就發生了:
這時候,由於輸入的B是『DEF』,並非一個數字,因此會被程式第17行的『Catch ex As Exception』例外處理程序所捕捉到,然後執行第18行顯示出錯誤訊息(從字串 "DEF" 轉換為型別 'Double' 是無效的)與發生位置(Microsoft.VisualBasic)。
請注意,當您輸入的值是英文字的時候,並不會被第9或13行的例外處理程序捕捉到,因為,當時的數值並非0,而是文字,所以處理的程序是第17行,然而,當我們真的輸入0時,又會如何呢?
這就是剛才提過挺有趣的部分,在.NET Framework中,居然不會有『除以零錯誤』,請注意,當我們把3/0時,結果並不會發生錯誤,因此第9、13、17行的錯誤處理程序完全派不上用場,只有第21行的『Finally』依舊老實的被執行了(記得嗎?只要進入錯誤處理程序,即使不發生錯誤,依舊會執行Finally後的敘述)。
在.NET Framework中,3/0的結果是→『正無窮大』!!!
『正無窮大』實際在記憶體內的表示為『1.#INF』,『正無窮大』為呼叫ToString傳回的結果。 『負無窮大』實際在記憶體內的表示為『-1.#INF』,『負無窮大』為呼叫ToString傳回的結果。 |
好樣的,.NET Framework還真是神奇,我們試試看另外一個狀況,我們把0除以0,看看結果如何?
程式照常執行,但是顯示出來的結果是『不是一個數字』。您會發現與傳統的程式設計有點不同,.NET Framework中捕捉了除以零的狀況(應該說是允許其發生),而將其賦予可呈現的值。
『不是一個數字』實際在記憶體內的表示為『-1.#IND』,『不是一個數字』為呼叫ToString傳回的結果。 |
從上面這個例子,可以看到Try…End Try結構的用法,在每個Try…End Try之中,一定要有至少一個Catch敘述,否則會發生錯誤,而Finally則不一定需要,另外Try…End Try敘述不可與On Error敘述同時存在,儘管Visual Basic.NET對這兩個敘述都支援。
沒有留言:
張貼留言