MasteringVFP/2/4/5
出自VFP Wiki
MasteringVFP/2/4/5
的原始碼
跳轉到:
導航
,
搜尋
根據以下的原因,您並無權限去做編輯這個頁面:
你所請求執行的操作被禁止。
你可以檢視並複製本頁面的原始碼。
= TRY...CATCH...FINALLY 命令 (8.0 新增) = == 用途 == :提供一個結構來處理執行一個程式碼區塊時可能發生的錯誤和異常。 == 語法 == :TRY ::[ ''tryCommands'' ] :[ CATCH [ TO ''!VarName'' ] [ WHEN ''lExpression'' ] ::[ ''catchCommands'' ] ] :[ EXIT ] :[ THROW ''eUserExpression'' ] :[ FINALLY ::[ ''finallyCommands'' ] ] :ENDTRY == 參數 == === TRY === *指出 TRY...CATCH...FINALLY 結構的開始。 === ''tryCommands'' === *指定可能發生錯誤的陳述式。 *如果發生錯誤,Visual !FoxPro 儲存一個 Exception 物件參照至 ''!VarName'' 記憶體變數中。程式執行直接到 CATCH 陳述式。 *如果沒有發生錯誤,程式執行到 FINALLY 陳述式。 === CATCH === *指明處理錯誤的 CATCH 區塊的開始。 *若 CATCH WHEN 求值結果為 .T. (真)時,可以指定一個不帶參數的 CATCH 陳述式。 *只有當一個錯誤在那個方法程序的 TRY 區塊中發生以及在方法程序中的程式碼導致例外的時候,CATCH 敘述式會被呼叫。 *如果另外的方法程序是從此 TRY 區塊裡面呼叫而導致一個錯誤時,Error 事件對那個方法程序來處理此錯誤。 *這行為發生是因為另一個方法程序可以直接或從一個不包含 TRY...CATCH...FINALLY 結構之不同的方法程序來呼叫。 *下列範例舉例說明這行為: :x = NEWOBJECT("myClass") :x.myMethod() :DEFINE CLASS myClass AS Session OLEPUBLIC : PROCEDURE myMethod : myMethod3() && Error 事件處理錯誤。 : TRY : THIS.myMethod2() : myMethod3() && CATCH 處理這個錯誤。 : CATCH TO oErr : ? "Catch:",oErr.!ErrorNo : FINALLY : ENDTRY : ENDPROC : PROCEDURE myMethod2 : x = y && y 變數不存在。 : && Error 事件處理這個錯誤。 : ENDPROC : PROCEDURE Error(nError, cMethod, nLine) : ? "Error:",nError : ENDPROC :ENDDEFINE :PROCEDURE myMethod3 : x = y :ENDPROC === TO ''!VarName'' === *指定一個用於儲存 Exception 物件參照至可選用的記憶體變數,它在 TRY 區塊中發生錯誤時會自動建立。 :''!VarName'' 只能是一個簡單的記憶體變數,不能是物件屬性參照。 *可以在 TRY...CATCH...FINALLY 結構中明確地設定 ''!VarName'' 為任何值。只要另一個 CATCH 敘述式沒有被執行(重設定 ''!VarName'' 為 NULL),該值不會改變。 *''!VarName'' 可以為 local(區域)、public(公共) 或 private(私有) 作用域,這取決於變數先前是如何定義的。 :如果 ''!VarName'' 在之前沒有定義,那麼它是 private。 :建立的 Exception 物件與 ''!VarName'' 具有相同的作用域。當 ''!VarName'' 超出作用域、被釋放或重設定時,Exception 物件也被釋放。 *當一個 CATCH TO ''!VarName'' 子句執行時,雖然 ''!VarName'' 保留它的作用域,Visual !FoxPro 總是設定 ''!VarName'' 記憶體變數為一個新的 Exception 物件而不管它早先的設定。因此,''!VarName'' 的內容總是被覆蓋而不管它先前的參照。 *如果存在一個 WHEN 子句,而且它的求值為假 (.F.) 時,Visual !FoxPro 釋放 Exception 物件並重設定 ''!VarName'' 為 NULL。 :你可以用 VARTYPE() 函數測試是否 ''!VarName'' 被設定為一個類型或是 NULL。 === WHEN ''lExpression'' === *指定一個可選用的在程式遇到 CATCH 敘述式是被求值的表達式。為了使相應的 ''catchCommands'' 執行,該表達式的值必須為真 (.T.)。 *''lExpression'' 參數可以包含一個 參照到 ''!VarName'' 的 Exception 物件,這樣你就可以檢查錯誤結果並處理它。 === ''catchCommands'' === *指定當程式遇到相應的 CATCH 敘述式時要執行的敘述式。 === THROW [ ''eUserExpression'' ] === *建立一個被 CATCH 陳述式接收的新 Exception 物件。 :''eUserExpression'' 參數指定一個任意類型的運算式並設定 Exception 物件的 !UserValue 屬性。 :通常在一個 CATCH 區塊中用一個 THROW 子句來增強對一個更高級的錯誤處理程式的錯誤或異常。 :你可以傳遞一個任意類型的物件,因為 Exception 的 !UserValue 只儲存物件參照。 *當你使用有 ''eUserExpression'' 參數的 THROW 子句時,Visual !FoxPro 設定 Exception 物件的 !ErrorNo 屬性值為 2071,相應於錯誤:User Thrown Error (錯誤 2071)。 :如果您省略 ''eUserExpression'' 且 Exception 物件存在,Visual !FoxPro 增強原始的 Exception 物件。 :如果 Exception 物件不存在,Visual !FoxPro 拋出一個新的、!ErrorNo 屬性值為 2071 的 Exception 物件。 **'''注意''' ::你應該為 ''eUserExpression'' 傳遞一個值,它設定 Exception 物件的 !UserValue 屬性,因為它允許你鏈接多個 Exception 物件。 ::關於鏈接 Exception 物件的相關資訊,請參見範例。 *如果你不包括 ''eUserExpression'',而且 THROW 子句增強對一個外部的 TRY...CATCH 區塊之 Exception 物件,相同的 Exception 物件由外部的 TRY...CATCH 區塊捕捉。 :當使用在一個結構化異常處理程式中,由 ERROR()、MESSAGE( ) 和 AERROR( ) 函數所傳來的值總是不可靠的,如此你應該使用 Exception 物件來替代。 *你能在一個 TRY...CATCH...FINALLY 結構中呼叫來自任何的程式碼區塊。然而,你能任意在一個存在捕捉異常的程式碼之錯誤處理程式中使用 THROW。 :你不能夠從命令視窗來呼叫 THROW。 **'''警告''' ::呼叫在 TRY...CATCH...FINALLY 結構外的 THROW 命令以及沒有一個適當的錯誤處理程式會導致你的程式結束。 *如果當 THROW 是從一個 CATCH 或 FINALLY 區塊所呼叫時,一個外部的 TRY...CATCH 陳述式是有效的,Visual !FoxPro 在 CATCH TO 子句指定 ''!VarName'' 為對拋出的異常所產生的 Exception 物件之物件參照。 :如果外部的 TRY...CATCH 陳述式是無效的,Visual !FoxPro 逐步上移異常到一個可能存在的 ON ERROR 或 ERROR 事件;否則,Visual !FoxPro 呼叫它的系統錯誤處理程式。 **'''注意''' ::執行時期應用程式應該正確地封裝 THROW 陳述式到一個外部的 TRY...CATCH...FINALLY 結構中。 *如果你想重新拋出原始的由 CATCH TO ''!VarName'' 子句所捕捉到的異常,你可以呼叫 THROW ''!VarName'' 來重新拋出異常。 **'''注意''' ::重新拋出原始的異常產生另一個新的 Exception 物件,在外部的 CATCH 陳述式中,有一個 !UserValue 屬性包含有原始異常的物件參照。 *Visual !FoxPro 忽略任何出現在 CATCH WHEN eExpression 子句中的 THROW 陳述式。 *如果 THROW 在評估一個運算式遇到一個錯誤時,Visual !FoxPro 以平常的方式上移錯誤。 === EXIT === *包括在一個 TRY、CATCH 或 FINALLY 區塊中來直接退出代碼區塊。 *如果 EXIT 出現在 TRY 或 CATCH 區塊中且 FINALLY 陳述式存在,程式再繼續執行 FINALLY 陳述式。 :如果 EXIT 出現在 FINALLY 區塊中或如果 FINALLY 不存在,程式再繼續執行到下一個 ENDTRY 陳述式。 === FINALLY === *指出 FINALLY 區塊的開始,在該區塊中你可以清除任何由 TRY 區塊分配的資源,除非使用了 CANCEL 和 QUIT 命令否則總是會執行該區塊中的程式碼。 *有關更多使用於 TRY...CATCH...FINALLY 結構中之命令的資訊,請參閱英文版的 Structured Error Handling (結構化錯誤處理)章節。 === ''finallyCommands'' === *指定要在 FINALLY 區塊中執行的陳述式,這些陳述式在 TRY 區塊中沒有發現錯誤或是執行了 CATCH 中的陳述式後執行。 === ENDTRY === *指出 TRY...CATCH...FINALLY 結構的結束。 :每個 TRY...CATCH...FINALLY 結構必須以 ENDTRY 關鍵字結束。 :與其它 Visual !FoxPro 控制項敘述式一樣,可以在前面加 && 符號來加入註釋到 ENDTRY 後面。 *如果在 TRY...CATCH...FINALLY 結構的尾端中沒有包括 ENDTRY 敘述式,當你編譯你的程式碼時 Visual !FoxPro 產生一個錯誤。 :雖然你仍然可以執行你有編譯錯誤的程式碼,但你不能這樣做,因為程序執行到此處時 Visual !FoxPro 會停止回應。 == 附註 == *就像在 Visual !FoxPro 中其他的錯誤處理程式,在 TRY...CATCH...FINALLY 異常處理程式中所發生的異常需設定 SET CONSOLE 命令為 ON。有關更多的資訊,請參閱 SET CONSOLE 命令。 *您不能夠明確地傳輸程式執行到一個 CATCH 或 FINALLY 程式碼區塊中。 *Visual !FoxPro 決定變數的範圍是在一個程序化上而不是以區塊為基準。 :也就是說,在 TRY 區塊中宣告的變數在同一個 TRY...CATCH...FINALLY 結構的 FINALLY 區塊中也是看得見的。 :但是,在一個巢狀的結構中,在 TRY、CATCH 或 FINALLY 區塊中所宣告的變數是屬於區域範圍。 *您不應在 TRY 區塊內部初始化變數或設定條件代碼,因為不能保證代碼會執行。 :如果一個錯誤出現在 TRY 區塊代碼中的特定列,所有在 TRY 區塊中後續的代碼將不會執行。 *任何發生在一個物件的 ERROR 事件中的錯誤是由該物件來處理的,而不是上移到 ON ERROR 常式或 TRY...CATCH...FINALLY 處理程式。 :然而,您可以在 ERROR 事件中使用一個 TRY...CATCH...FINALLY 結構來找出來自一個 ERROR 事件的錯誤。有關更多的資訊,請參閱 ERROR 事件。 *在 CATCH 區塊中用 COMRETURNERROR() 函數結束所有進一步的處理並直接傳回程式控制到元件物件模型 (Component Object Model;COM) 用戶端。 :因此,如果你有一個 FINALLY 區塊,它不會執行。有關更多的資訊,請參閱 COMRETURNERROR( ) 函數。 *避免在 TRY...CATCH...FINALLY 結構中使用 SET TEXTMERGE TO MEMVAR 命令,因為如果在陳述式中發生錯誤記憶體變數將變將會被遺失。 *可以在你的 TRY...CATCH...FINALLY 程式碼中用 SYS(2410) - 錯誤處理程式函數來檢測動作過程,例如:用一個 DO CASE 結構,藉由處理程式類型來處理異常。有關更多的資訊,請參閱 SYS(2410) - 錯誤處理程式。 *如果結構封裝正確,您可以使用 TRY...CATCH...FINALLY 和像 ON KEY LABEL 這樣的命令來處理出現在功能表和計時器事件中的錯誤。 :下面範例說明 READ EVENTS 命令如何在一個 TRY...CATCH...FINALLY 結構中保持程式控制,因此可以捕捉功能表事件。 :錯誤捕捉是由 TRY...CATCH...FINALLY 在呼叫堆疊的位置控制的。 <pre> TRY DO myMenu.mpr DO FORM myForm myForm.!AddObject("tm1","mytimer") READ EVENTS CATCH TO oException IF oException.!ErrorNo = 1 ENDIF FINALLY CLEAR EVENTS ENDTRY </pre> :有關更多的資訊,請參閱 READ EVENTS 命令和 ON KEY LABEL 命令。 *Visual !FoxPro 僅在單一的程式碼區塊中支援 Set Next Statement 除錯功能。例如:當執行 TRY 區塊中的程式碼時,你只能用 Set Next Statement 到另一 TRY 區塊中的另一行。你不能夠跳到在 CATCH 或 FINALLY 區塊中別的行。有關更多的資訊,請參閱除錯程式鍵盤快速鍵和功能表 (Debugger Keyboard Shortcuts and Menus)。 *Visual !FoxPro 在以下條件下產生錯誤信息: :#在 TRY...CATCH...FINALLY 結構中出現不相符或錯誤。 :#一個不能處理的異常發生。 :#一個不被允許的命令出現在一個 TRY、CATCH 或 FINALLY 區塊中的特定區塊。有關更多的資訊,請參閱結構化錯誤處理程式 (Structured Error Handling)。 :#一個使用者上拋錯誤發生。 == 範例 == 下列範例說明如何在巢狀的 TRY...CATCH 陳述式中使用 THROW 子句以及處理 Exception 物件: <pre> LOCAL x ,y ,result && 整數 LOCAL oErr , oErr1 && Exception 物件 TRY x = 1 TRY USE nothing GO TOP y = nothing.col1 CATCH TO oErr oErr.!UserValue = "巢狀的 CATCH 訊息:不能處理" ?[:巢狀的 Catch!(無法處理:上拋至 oErr 物件上) ] ?[ 內部 Exception 物件:] ?[ 錯誤:] + STR(oErr.!ErrorNo) ?[ 列數:] + STR(oErr.!LineNo) ?[ 訊息:] + oErr.Message ?[ 程序:] + oErr.Procedure ?[ 詳細資料:] + oErr.Details ?[ 堆疊層級:] + STR(oErr.!StackLevel) ?[ 列內容:] + oErr.!LineContents ?[ !UserValue:] + oErr.!UserValue THROW oErr FINALLY ?[:巢狀的 FINALLY 被執行] IF USED("nothing") USE IN nothing ENDIF ENDTRY result = x - y CATCH TO oErr1 ?[:外部 CATCH!] ?[ 外部 Exception 物件:] ?[ 錯誤:] + STR(oErr1.!ErrorNo) ?[ 列數:] + STR(oErr1.!LineNo) ?[ 訊息:] + oErr1.Message ?[ 程序:] + oErr1.Procedure ?[ 詳細資料:] + oErr1.Details ?[ 堆疊層級:] + STR(oErr1.!StackLevel) ?[ 列內容:] + oErr1.!LineContents ?[ ->!UserValue becomes inner exception THROWn from nested TRY/CATCH ] ?[ 錯誤:] + STR(oErr1.!UserValue.!ErrorNo) ?[ 訊息:] + oErr1.!UserValue.Message ?[ 程序:] + oErr1.!UserValue.Procedure ?[ 詳細資料:] + oErr1.!UserValue.Details ?[ 堆疊層級:] + STR(oErr1.!UserValue.!StackLevel) ?[ 列內容:] + oErr1.!UserValue.!LineContents ?[ !UserValue:] + oErr1.!UserValue.!UserValue result = 0 FINALLY ?[:FINALLY 陳述式被執行] ENDTRY RETURN result </pre> 下列範例顯示如何去連結 Exception 物件: <pre> TRY TRY x = y && y 變數不存在造成一個錯誤。 CATCH TO oException2 THROW CREATEOBJECT("myException") ENDTRY CATCH TO oException1 ENDTRY ? 2, oException2.!ErrorNo, oException2.!UserValue ? 1, oException1.!ErrorNo, oException1.!UserValue.!UserValue DEFINE CLASS myException AS Exception !UserValue = "我自定的錯誤處理程式" PROCEDURE Init STRTOFILE("一個錯誤發生在:" + TRANSFORM(DATETIME()) + CHR(13),"c:\errs.log",.T.) ENDPROC ENDDEFINE </pre>
返回到
MasteringVFP/2/4/5
。
檢視
頁面
討論
原始碼
歷史
個人工具
登入/建立新帳號 選單
導航
首頁
社群入口
現時事件
近期變動
隨機頁面
使用說明
搜尋
工具箱
鏈入頁面
相關頁面修訂記錄
所有特殊頁面