調試信息
可使用如下兩個命令輸出調試信息:
l Debug.WriteLine()
l Trace.WriteLine()
這兩個命令函數的用法幾乎完全相同,但有一個重要區別。第一個命令僅在調試模式下運行,而第二個命令還可用於發布程序。實際上,Debug.WriteLine()命令甚至不能編譯為可發布的程序。這兩個函數包含在System.Diagnostics名稱空間中。
這兩個函數的第一個字符串參數用於輸出消息,而不需要使用{X}語法插入變量值。這意味着必須使用+等串聯運算符在字符串種插入變量值。它們還可以有第二個字符串參數,用於顯示輸出文本的類別。
這些函數的一般輸出為: <category>: <message>
這些函數中可使用string.Format()函數把變量值嵌套在字符串種,這比使用+串聯運算符更加高效。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Diagnostics; 7 8 namespace ConsoleApplication1 9 { 10 class Program 11 { 12 13 14 static void Main(string[] args) 15 { 16 int[] testArray = { 4,7,4,2,7,3,7,8,3,9,1,9}; 17 int[] maxValIndices; 18 int maxNum = GetMax(testArray, out maxValIndices); 19 Console.WriteLine("The max number in the array is {0},found at element indicies:",maxNum); 20 foreach (int i in maxValIndices) 21 { 22 Console.WriteLine(i); 23 } 24 25 Console.ReadLine(); 26 } 27 28 static int GetMax(int[] nums, out int[] indicies) 29 { 30 int iMax = nums[0]; 31 int count = 1; 32 indicies = new int[1]; 33 indicies[0] = 0; 34 35 Debug.WriteLine(string.Format("Maximum value initialized to {0} at element index 0.",iMax)); 36 37 for (int i = 1; i < nums.Length; i++) 38 { 39 Debug.WriteLine(string.Format("Now looking at element at index {0}.",i)); 40 if (nums[i] > iMax) 41 { 42 iMax = nums[i]; 43 count = 1; 44 indicies = new int[1]; 45 indicies[0] = i; 46 Debug.WriteLine(string.Format("New maximum found. New value is {0}, at element index {1}.",iMax,i)); 47 } 48 else if (nums[i] == iMax) 49 { 50 int[] oldIndex = indicies; 51 count++; 52 indicies = new int[count]; 53 oldIndex.CopyTo(indicies, 0); 54 indicies[count - 1] = i; 55 Debug.WriteLine(string.Format("Duplicate maximum found at element index {0}",i)); 56 } 57 } 58 Trace.WriteLine(string.Format("maximum value {0} found, with {1} occurences.",iMax,count)); 59 Debug.WriteLine("Maximum value search completed."); 60 return iMax; 61 } 62 63 } 64 }
還有下列命令:
- Debug.WriteLineIf()
- Trace.WriteLineIf()
- Debug.WriteIf()
- Trace.WriteIf()
這些參數增加了一個必須參數,且該參數放在列表參數的最前面。這個參數的值為布爾值(或者計算結果為布爾值的表達式),只有這個值為true時,函數才會輸出文本。使用這些函數可以有條件地把文本輸出到Output窗口中。
跟蹤點
另一種把信息輸出到Output窗口中的方法是使用跟蹤點。其作用與使用Debug.WriteLine()相同。它實際上是輸出調試信息且不修改代碼的一種方式。
方法: 把光標放在要插入跟蹤點的代碼行上。注意,跟蹤點會在執行這行代碼之前被處理。如果要輸出變量值,應把變量名放在花括號中。
診斷輸出與跟蹤點
跟蹤點與Trace命令並不等價,也就是說,不能使用跟蹤點在發布版本中輸出信息。這是因為跟蹤點並沒有包含在應用程序中。跟蹤點的主要缺點也是其優點,即他們存儲在VS中,因此可以在需要時快速、方便地添加到應用程序中,而且也非常容易刪除。其另一個優點是允許方便地添加額外的信息,如$FUNCTION。總之,輸出調試信息的兩種方法是:
l 診斷輸出: 總是要從應用程序中輸出調試結果時使用這種方法,尤其是在要輸出的字符串比較復雜,涉及幾個變量或許多信息的情況下,使用該方法比較好。另外,如果要在發布模式下獲得執行應用程序的調試結果,Trace命令常常是唯一的選擇。
2 跟蹤點: 調試應用程序時,希望快速輸出重要信息,以便解決語義錯誤,應使用跟蹤點。
另一個明顯的區別是跟蹤點只能在VS中使用,而診斷輸出可以在VS和VCE中使用。
進入中斷模式
- 在運行應用程序時,單擊IDE中的Pause按鈕。
- 斷點。
- 在拋出一個未處理的異常時選擇進入中斷模式。
- 生成一個判定語句(assertion)時中斷。
判定語句時可以用用戶定義的消息中斷應用程序的指令。當遇到判定語句時,可以選擇Abort,中斷應用程序的執行,也可以選擇Retry,進入中斷模式,還可以選擇Ignore,讓應用程序像往常一樣繼續執行。
與調試輸出函數一樣,判定函數也有兩個版本:
- Debug.Assert()
- Trace.Assert()
其調試版本也是僅用於編譯調試程序。
這兩個函數帶3個參數。第一個參數是一個布爾值,其值為false會觸發判定語句。第二、三個參數是兩個字符串,分別把信息寫到彈出的對話框和Output窗口中。
Immediate和Command窗口
Command和Immediate窗口可以在運行應用程序的過程中執行命令。通過Command窗口可以手動執行VS操作,Immediate窗口可以執行源代碼,計算表達式,還可以執行其他代碼。
輸入命令immed,可以從Command窗口切換到Immediate窗口;輸入>cmd可以從Immediate窗口切換到Command窗口。
Call Stack窗口
Call Stack窗口描述了程序是如何執行到當前位置的。
結構化異常處理(Structured Exception Handling, SEH)
如果有一個或多個catch塊,finally塊就是可選的,否則就是必須的。
可以使用表達式throw; 在catch塊中拋出異常。這個表達式會再次拋出catch塊處理過的異常。如果以這種方式拋出異常,該異常就不會由當前的try...catch...finally快處理,而是由上一級的代碼處理。