使用 DebuggerDisplay 屬性
DebuggerDisplay 屬性 (System.Diagnostics.DebuggerDisplayAttribute) 負責控制類別或欄位在偵錯工具變數視窗中顯示的方式。 這個屬性可以套用至:
類別
Structs
委派
列舉
欄位
屬性
組件
DebuggerDisplay 屬性有單一引數,這是要在類型執行個體的 [值] 一欄中顯示的字串。 這個字串可以包含括號 ({ 和 })。 在一對括號內的文字將會評估為欄位、屬性或方法。
如果 C# 物件具有覆寫的 ToString(),則偵錯工具會呼叫覆寫並顯示它的結果,而不是標準的 {<typeName>}。 因此,如果您具有覆寫的 ToString(),就不需要使用 DebuggerDisplay。 如果兩者都使用,DebuggerDisplay 屬性則會優先於 ToString() 覆寫。
偵錯工具是否會評估這個隱含 ToString() 呼叫,取決於 [選項] 對話方塊中的使用者設定 ([偵錯] 分類、[一般] 頁面)。 Visual Basic 並未實作這個隱含 ToString() 評估。
重要
如果已在 [工具選項] 對話方塊中選取 [在變數視窗中顯示物件的原始結構] 核取方塊,則會忽略 DebuggerDisplay 屬性。
下表說明 DebuggerDisplay 屬性的一些可能用法和範例輸出。
屬性 |
出現在 [值] 欄中的輸出 |
---|---|
[DebuggerDisplay("x = {x} y = {y}")] 用於具有 x 和 y 欄位的類型。 |
x = 5 y = 18 |
[DebuggerDisplay("String value is {getString()}")]參數語法會因語言而有所不同。 因此,請小心使用。 |
String value is [5, 6, 6] |
DebuggerDisplay 也可以接受具名參數。
參數 |
用途 |
---|---|
Name, Type |
這些參數會影響變數視窗的 [名稱] 和 [類型] 欄 (它們可以設定為與建構函式使用相同語法的字串)。過度使用或不當使用這些參數,會造成輸出混淆。 |
Target, TargetTypeName |
指定屬性在組件層級使用時的目標類型。 |
注意事項 |
---|
autoexp.cs 檔案會在組件層級使用 DebuggerDisplay 屬性。autoexp.cs 檔案會決定 Visual Studio 用於 C# 變數的預設展開。您可以查看 autoexp.cs 檔案取得 DebuggerDisplay 屬性的使用範例,也可以修改和編譯 autoexp.cs 檔案變更預設展開。請務必先備份 autoexp.cs 檔案,再進行修改。您必須參考 \Program Files\Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies 中的 Microsoft.VisualStudio.DebuggerVisualizers.dll。autoexp.cs 檔案位於 My Documents/Visual Studio 2012/Visualizers 中。 |
在 DebuggerDisplay 中使用運算式
雖然您可以在 DebuggerDisplay 屬性中使用大括號括住的一般運算式,但不建議採取這種做法。
DebuggerDisplay 中的一般運算式只能隱含存取目標類型之目前執行個體的 this 指標。 運算式無法存取別名、區域變數或指標。 如果運算式參考屬性 (Property),則不會處理這些屬性 (Property) 中的屬性 (Attribute)。 例如,如果欄位 count 為 8,則 C# 程式碼 [DebuggerDisplay("Object {count - 2}" 會顯示 Object 6。
在 DebuggerDisplay 中使用運算式可能導致下列問題:
評估運算式是偵錯工具中最昂貴的作業,而且每次顯示運算式時都會進行評估。 這可能會在逐步執行程式碼時導致效能問題。 例如,若集合或清單中的元素數目很大,則用於顯示其中值的複雜運算式執行速度可能會非常慢。
運算式是由使用目前堆疊框架語言的運算式評估工具進行評估,而不是由撰寫運算式之語言的評估工具進行評估。 這種情況可能會在語言不同時導致無法預測的結果。
評估運算式可能會變更應用程式的狀態。 例如,設定屬性值的運算式會改變執行程式碼中的屬性值。
減少運算式評估可能出現之問題的其中一種方法,是建立私用屬性來執行作業並傳回字串。 這樣 DebuggerDisplay 屬性就可以顯示該私用屬性的值。 下列範例將實作這個模式:
[DebuggerDisplay("{DebuggerDisplay,nq}")]public sealed class MyClass { public int count { get; set; } public bool flag { get; set; } private string DebuggerDisplay { get{ return string.Format("("Object {0}", count - 2); } }}
範例
下列程式碼範例將示範如何使用 DebuggerDisplay 搭配 DebuggerBrowseable 和 DebuggerTypeProxy。 在偵錯工具變數視窗中檢視時 (例如 [監看式] 視窗),它會產生類似下面所示的展開:
名稱 |
值 |
類型 |
---|---|---|
Key |
"three" |
object {string} |
值 |
3 |
object {int} |
[DebuggerDisplay("{value}", Name = "{key}")]
internal class KeyValuePairs
{
private IDictionary dictionary;
private object key;
private object value;
public KeyValuePairs(IDictionary dictionary, object key, object value)
{
this.value = value;
this.key = key;
this.dictionary = dictionary;
}
public object Key
{
get { return key; }
set
{
object tempValue = dictionary[key];
dictionary.Remove(key);
key = value;
dictionary.Add(key, tempValue);
}
}
public object Value
{
get { return this.value; }
set
{
this.value = value;
dictionary[key] = this.value;
}
}
}
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable
{
public Hashtable hashtable;
public MyHashtable()
{
hashtable = new Hashtable();
} private string DebuggerDisplay { get { return "Count = " + hashtable.Count); } }
private class HashtableDebugView
{
private MyHashtable myhashtable;
public HashtableDebugView(MyHashtable myhashtable)
{
this.myhashtable = myhashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePairs[] Keys
{
get
{
KeyValuePairs[] keys = new KeyValuePairs[myhashtable.hashtable.Count];
int i = 0;
foreach (object key in myhashtable.hashtable.Keys)
{
keys[i] = new KeyValuePairs(myhashtable.hashtable, key, myhashtable.hashtable[key]);
i++;
}
return keys;
}
}
}
}