Visual Studio 調試器 Managed 程式碼中的斷言
(2008-05-29 00:20)
Visual Studio 調試器Managed 程式碼中的斷言
斷言(或 Assert 語句)測試您作為 Assert 語句的參數指定的條件。如果此條件計算為 true,不發生操作。如果此條件計算為 false,則宣告失敗。如果正在調試版本中運行,則程式進入中斷模式。
在 Visual Basic 和 Visual C# 中,可以從 Debug 或 Trace 中使用 Assert 方法,這兩種方法都在 System.Diagnostics 命名空間中。由於 Debug 類方法未包含在程式的“發布”版本中,所以它們不會增加發布代碼的大小或降低其速度。
C++ 不支援 Debug 類方法。使用帶有條件編譯的 Trace 類(如 #ifdef DEBUG...)可獲得同樣的效果。 #endif.
Debug.
Assert 方法
可隨意使用 System.Diagnostics.Debug.Assert(System.Boolean) 方法測試條件,如果代碼正確,該條件應保持為真。例如,假設已編寫一個整數除法函數。根據數學規則,除數永遠不能為零。可以使用斷言測試該條件:
[Visual Basic]
Function IntegerDivide(ByVal dividend As Integer, ByVal divisor As Integer) As Integer Debug.Assert(divisor <> 0) Return CInt(dividend / divisor) End Function
[C#]
int IntegerDivide ( int dividend , int divisor ) { Debug.Assert ( divisor != 0 ); return ( dividend / divisor ); }
當在調試器下運行該代碼時,將計算Assert 陳述式,但是在發布版本中,將不進行該比較,因此沒有額外的系統開銷。
以下是另一個樣本。您有一個實現支票活期存款帳戶的類,如下所示:
[Visual Basic]
Dim amount, balance As Double balance = savingsAccount.balance Debug.Assert(amount <= balance) SavingsAccount.Withdraw(amount)
[C#]
float balance = savingsAccount.Balance; Debug.Assert ( amount <= balance ); savingsAccount.Withdraw ( amount );
在從該帳戶中提取錢之前,您想要確保帳戶的餘額大於準備取出的金額。可以編寫檢查餘額的斷言:
[Visual Basic]
Dim amount, balance As Double balance = savingsAccount.balance Trace.Assert(amount <= balance) SavingsAccount.Withdraw(amount)
[C#]
float balance = savingsAccount.Balance; Trace.Assert ( amount <= balance ); savingsAccount.Withdraw ( amount );
注意,當建立代碼的發布版本時,對System.Diagnostics.Debug.Assert(System.Boolean) 方法的調用將消失。這意味著在發布版本中檢查餘額的調用將消失。若要解決此問題,您應使用不會在發布版本中消失的System.Diagnostics.Trace.Assert(System.Boolean) 替換System.Diagnostics.Debug.Assert(System.Boolean):
與對 System.Diagnostics.Debug.Assert(System.Boolean) 的調用不同,對System.Diagnostics.Trace.Assert(System.Boolean) 的調用會增加發布版本的系統開銷。
Debug.
Assert 的副作用
使用 System.Diagnostics.Debug.Assert(System.Boolean) 時,確保 Assert 中的任何代碼不會更改程式的結果(如果移除 Assert)。否則,可能會意外地引入一個只在程式的發布版本中出現的 bug。對於包含函數或程序呼叫的斷言要特別小心,如下面的樣本:
[Visual Basic]
' unsafe code Debug.Assert (meas(i) <> 0 )
[C#]
// unsafe code Debug.Assert (meas(i) != 0 );
乍一看,使用 System.Diagnostics.Debug.Assert(System.Boolean) 似乎很安全,但是假設每次調用函數 meas 時該函數都會更新計數器。當產生發布版本時,由於消除了對 meas 的調用,因此計數器將得不到更新。這是一個帶“副作用”的函數的樣本。消除對具有副作用的函數的調用會導致一個只出現在發布版本中的 bug。為避免這樣的問題,請不要將函數調用放在System.Diagnostics.Debug.Assert(System.Boolean) 語句中。改用臨時變數:
[Visual Basic]
temp = meas( i ) Debug.Assert (temp <> 0)
[C#]
temp = meas( i ); Debug.Assert ( temp != 0 );
即使在使用 System.Diagnostics.Trace.Assert(System.Boolean) 時,也需要避免將函數調用放置到 Assert 語句中。這樣的調用應是安全的,因為在發布版本中沒有消除System.Diagnostics.Trace.Assert(System.Boolean) 語句。但是,如果習慣上避免這樣的結構,則使用 System.Diagnostics.Debug.Assert(System.Boolean) 時犯錯誤的可能性很小。
Trace 和 Debug 的要求
如果使用 Visual Studio 嚮導建立項目,則預設情況下,“發布”配置和“調試”配置中都定義了 TRACE 符號。預設情況下,只在調試版本中定義 DEBUG 符號。
否則,若要使 Trace 方法工作,程式必須在源檔案的頂部放置以下代碼之一:
或者,程式必須是用 TRACE 選項產生的:
如果需要在 C# 或 Visual Basic 發布版本中使用 DEBUG 方法,必須在“Release”配置中定義 DEBUG 符號。
C++ 不支援 Debug 類方法。使用帶有條件編譯的 Trace 類(如 #ifdef DEBUG...)可獲得同樣的效果。#endif 可以在“<Project> 屬性頁面”對話方塊中定義這些符號。有關更多資訊,請參見為 Visual Basic 調試配置更改項目設定或更改 C 或 C++ 調試配置的項目設定。)
Assert 參數
System.Diagnostics.Trace.Assert(System.Boolean) 和System.Diagnostics.Debug.Assert(System.Boolean) 最多有三個參數。第一個參數是強制的,它是想要檢查的條件。如果僅用一個參數來調用System.Diagnostics.Trace.Assert(System.Boolean) 或System.Diagnostics.Debug.Assert(System.Boolean),Assert 方法將檢查條件,並且如果結果是 false,則向“輸出”視窗輸出呼叫堆疊的內容。下面的樣本顯示System.Diagnostics.Trace.Assert(System.Boolean) 和System.Diagnostics.Debug.Assert(System.Boolean):
[Visual Basic]
Debug.Assert(stacksize > 0) Trace.Assert(stacksize > 0)
[C#]
Debug.Assert ( stacksize > 0 ); Trace.Assert ( stacksize > 0 );
第二個和第三個參數(如果有)必須是字串。如果調用帶有兩個或三個參數的System.Diagnostics.Trace.Assert(System.Boolean) 或System.Diagnostics.Debug.Assert(System.Boolean),則第一個參數是一個條件。該方法檢查此條件,如果結果為 false,則輸出第二個和第三個字串。下面的樣本示範System.Diagnostics.Debug.Assert(System.Boolean,System.String) 和System.Diagnostics.Trace.Assert(System.Boolean,System.String) 使用兩個參數的情況:
[Visual Basic]
Debug.Assert(stacksize > 0, "Out of stack space") Trace.Assert(stacksize > 0, "Out of stack space")
[C#]
Debug.Assert ( stacksize > 0, "Out of stack space" ); Trace.Assert ( stacksize > 0, "Out of stack space" );
下面的樣本顯示 Assert 和 Assert:
[Visual Basic]
Debug.Assert(stacksize > 0, "Out of stack space. Bytes left:" , Format(size, "G"))Trace.Assert(stacksize > 0, "Out of stack space. Bytes left:" , Format(size, "G"))Trace.Assert(stacksize > 0, "Out of stack space. Bytes left:", "inctemp failed on third call" )
[C#]
Debug.Assert ( stacksize > 100, "Out of stack space" , "Failed in inctemp" );Trace.Assert ( stacksize > 0, "Out of stack space", "Failed in inctemp" ); 自訂 Assert 行為
如果在使用者介面模式中運行應用程式,則當條件失敗時,Assert 方法將顯示“宣告失敗”對話方塊。宣告失敗時發生的操作是由 Listeners 或 Listeners 屬性控制的。
可以通過向 Listeners 集合添加 TraceListener 對象、從 Listeners 集合移除TraceListener 或者重寫現有 TraceListener 的System.Diagnostics.TraceListener.Fail(System.String) 方法來自訂輸出行為,使其行為不同。
例如,可以重寫 System.Diagnostics.TraceListener.Fail(System.String) 方法來寫入事件記錄而不是顯示“宣告失敗”對話方塊。
若要以這種方法自訂輸出,則程式必須包含接聽程式,並且必須從 TraceListener 繼承並重寫它的 System.Diagnostics.TraceListener.Fail(System.String) 方法。
有關更多資訊,請參見跟蹤接聽程式。
在設定檔中設定斷言
您可以在程式設定檔和代碼中設定斷言。有關更多資訊,請參見System.Diagnostics.Trace.Assert(System.Boolean) 或System.Diagnostics.Debug.Assert(System.Boolean)。