Visual Studio內建有如此之多有用的除錯特性,但並非眾所周知。本文列舉一些我的最愛,包括最近我在 VS2013 中發現的除錯特性。
1.在Lambda表示式中的斷點
如果你點選左邊欄設定斷點,你可能很容易被誤導認為斷點發生在行級別上。實際上,你可以在行內部插入斷點,如在你的LINQ的Lamdba表示式中。僅需右擊程式碼部分並且從選單選擇Breakpoint > Insert breakpoint。
2.便捷的輸出視窗
輸出視窗對除錯很有用,同樣斷點也是彈出式或中斷程式的,但它確實很嘈雜。僅需右擊輸出視窗(要確保輸出被設為除錯),關閉Module Load,Module Unload,Process Exit 和Thread Exit 以只輸出你關心的內容。現在用Debug.WriteLine給出你真正關心的內容吧。
你也可以在輸出視窗使用Ctrl-S儲存設定。
3.在客戶端和伺服器端附加除錯(VS2012)
伺服器端和客戶端工程在一個solution中是有用的,你僅需要一份Visual Studio執行時拷貝而且也不會在alt-tab鍵的前進後退中迷失,特別是當它們使用共同的程式碼如資料結構工程。
有一個缺點,start-up工程是唯一獲得附加除錯的工程。如果你遇到異常,它會顯示在你的客戶端,而不是服務端。
現在這個問題很容易解決了。右擊solution,選擇properties > Multiple startup projects,然後選擇Start動作為你需要附加除錯的工程。
4.建立可重建工程模板
如果你負責SDK或者API,建立一個你獨用的簡單的應用程式。然後使用File > Export template儲存它。
現在你隨時可以從你的模板建立一個新的工程,僅需要一些點選。更好的做法是使得使用者和測試者能夠使用它們,以便他們給你最小的重建。
5.使用DebuggerDisplay屬性
偵錯程式預設會使用ToString()來監視並在視窗正常輸出類名。即使你重寫ToString,對其他除錯者也不見得一目瞭然。
在你的類中通過一句簡單的表示式,而不是改變屬性值來使用DebuggerDisplay。例如:
1 2 3 4 |
[DebuggerDisplay("Order {ID,nq}") class Order { public string ID { get { return id; } } } |
“nq”阻止了雙引號發散。你也可以在這裡使用方法,但是別做任何可能帶來微小副作用的事,否則你觀察的物件可能改變其行為,並導致奇怪的事發生。
6.管理斷點
你建立了一些帶勁的斷點,現在你要關閉其中的一個,因為它被點選了太多次,但你馬上又要再次用到它。如果你刪除了這個斷點,你就不得不回來再找到斷點位置。
開啟常被忽視的Breakpoints視窗(Ctrl-Alt-B)。這個視窗顯示了你設定的所有的斷點但關鍵的是允許你使它們無效僅僅通過去除check標記。再次check上以重新使它有效。
這個視窗同樣提供了快速除錯的功能:
- 條件 斷點什麼時候發生
- 發生次數 觀察多長時間發生一次並基於該次數中斷
- 標籤 斷點在分支中允許有效和無效
- 何時發生 在輸出視窗顯示一條訊息以代替真實的中斷
7.斷開或輸出呼叫者資訊(.NET 4.5/Windows 8 Store)
沒有為呼叫程式當前方法準備的全域性變數,並且得到當前棧內容是一個非常慢的操作。
一個快速簡單的手段是,為方法增加一個額外的可選字元型引數了,用CallerMemberName屬性。例如,
1 2 3 |
void MyFunction(string someValue, [CallerMemberName] string caller = null) { ... } |
因為這是可選的值,你不必修改任何呼叫程式,但現在你能:
①基於呼叫程式變數,在某些程式中設定斷點條件
②向日志檔案或者輸出視窗輸出呼叫程式內容
你也可以使用CallerLineNumber 和CallerFilePath。同樣記住建構函式,終結器和運算子過載將會顯示它們的相關方法名(.ctor,op_Equals等等)。
8.監視方法返回值(VS2013, .NET 4.5/Windows 8.1 Store)
有時你想看看方法返回值但對你來說並不容易,因為它是另一個方法的輸入引數,所以你並沒有儲存該值。
這個功能被加到VS2013中,但是它卻非常容易錯過,你不得不在正確的時間和正確的地方使用它。正確的地方是 Autos視窗,正確的時間是剛好回到方法被呼叫的地方這一步。當在你呼叫方法之前或者在方法體中時你看不到這個。它是一個單一步驟,像這樣:
箭頭標明它是返回值,並且讓你知道和它相關的方法名。
寫在最後
我也不得不強調,一旦軟體離開了你的機器,記錄日誌對問題解決是多麼有效。但這是一個比這個更大的議題。
我是不是遺漏了一些更好的除錯建議?在下面的回覆中隨時讓我知道吧。
附:Michael Parshin也有一些除錯的很棒的建議。