使用偵錯工具顯示屬性增強偵錯功能
注意
本文專屬於 .NET Framework。 其不適用於較新的 .NET 實作,包括 .NET 6 和更新版本。
偵錯工具顯示屬性能讓指定並最了解該類型執行階段行為的開發人員,也指定該類型在偵錯工具中顯示的外觀。 此外,提供 Target
屬性的偵錯工具顯示屬性,也可供沒有原始程式碼背景的使用者在組件層級使用。 DebuggerDisplayAttribute 屬性控制類型或成員在偵錯工具變數視窗中顯示的方式。 DebuggerBrowsableAttribute 屬性決定欄位或屬性是否以及如何顯示在偵錯工具變數視窗中。 DebuggerTypeProxyAttribute 屬性會指定類型的替代類型 (或 Proxy),並且變更在偵錯工具視窗中顯示類型的方式。 當您檢視有 Proxy (或替代類型) 的變數時,Proxy 會替代偵錯工具顯示視窗中的原始類型。 偵錯工具變數視窗只會顯示 proxy 型別的 Public 成員。 私用成員不會顯示。
使用 DebuggerDisplayAttribute
DebuggerDisplayAttribute 建構函式有單一引數:在類型執行個體的 [值] 一欄中顯示的字串。 這個字串可以包含括弧 ({ 和 })。 括弧內的文字會評估為運算式。 例如,下列 C# 程式碼會在選取加號 (+) 時顯示 "Count = 4",展開偵錯工具顯示的 MyHashtable
執行個體。
[DebuggerDisplay("Count = {count}")]
class MyHashtable
{
public int count = 4;
}
不處理套用至運算式參考屬性 (property) 的屬性 (attribute)。 在 C# 編譯器,一般運算式僅能以隱含方式存取目標類型目前執行個體的此一參考。 運算式有限制,不能存取別名、區域變數或指標。 在 C# 程式碼中,您可以使用以括弧括住的一般運算式,以隱含方式存取目標類型目前執行個體的 this
指標。
例如,如果 C# 物件具有覆寫的 ToString()
,則偵錯工具會呼叫覆寫並顯示它的結果,而不是標準的 {<typeName>}.
。因此,如果您已覆寫 ToString()
,就不需要使用 DebuggerDisplayAttribute。 如果兩者都使用,DebuggerDisplayAttribute 屬性則會優先於 ToString()
覆寫。
使用 DebuggerBrowsableAttribute
將 DebuggerBrowsableAttribute 套用至欄位或屬性,以指定欄位或屬性在偵錯工具視窗中的顯示方式。 這個屬性的建構函式會使用其中一個 DebuggerBrowsableState 列舉值,指定下列狀態之一:
Never 指出成員未顯示在資料視窗中。 例如,對欄位的 DebuggerBrowsableAttribute 使用此值,會從階層中移除欄位;當您按一下類型執行個體的加號 (+) 展開封入類型時,不會顯示欄位。
Collapsed 指出已顯示成員,但預設不展開。 這是預設行為。
RootHidden 指出成員本身不會顯示,但如果它是陣列或集合,則會顯示其組成物件。
注意
.NET Framework 2.0 版中的 Visual Basic 不支援 DebuggerBrowsableAttribute。
下列程式碼範例示範,使用 DebuggerBrowsableAttribute 防止它後面的屬性出現在類別的偵錯視窗中。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";
使用 DebuggerTypeProxy
當您需要大幅並從本質上變更類型的偵錯檢視,但不是變更類型本身時,請使用 DebuggerTypeProxyAttribute 屬性。 DebuggerTypeProxyAttribute 屬性用來指定類型的顯示 Proxy,讓開發人員調整類型的檢視。 這個屬性,如 DebuggerDisplayAttribute,可以用在組件層級;如此 Target 屬性會指定要使用 Proxy 的類型。 建議的用法是,這個屬性指定的私用巢狀類型,會出現在要套用屬性的類型內。 顯示類型時,支援類型檢視器的運算式評估工具會檢查這個屬性。 如果找到屬性,運算式評估工具會用顯示 Proxy 類型替代套用屬性的類型。
當 DebuggerTypeProxyAttribute 出現時,偵錯工具變數視窗只會顯示 Proxy 類型的 Public 成員。 私用成員不會顯示。 屬性增強的檢視不會變更資料視窗的行為。
為避免不必要的效能損失,在使用者按一下資料視窗中類型旁的加號 (+),或者套用 DebuggerBrowsableAttribute 屬性展開物件之前,不會處理顯示 Proxy 的屬性。 因此,顯示類型不建議套用任何屬性。 屬性可以而且應該套用在顯示類型的主體中。
下列程式碼範例示範使用 DebuggerTypeProxyAttribute 指定類型,用為偵錯工具的顯示 Proxy。
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
private const string TestString =
"This should not appear in the debug window.";
internal class HashtableDebugView
{
private Hashtable hashtable;
public const string TestStringProxy =
"This should appear in the debug window.";
// The constructor for the type proxy class must have a
// constructor that takes the target type as a parameter.
public HashtableDebugView(Hashtable hashtable)
{
this.hashtable = hashtable;
}
}
}
範例
描述
您可以在 Visual Studio 中檢視下列程式碼範例,查看套用 DebuggerDisplayAttribute、DebuggerBrowsableAttribute 和 DebuggerTypeProxyAttribute 屬性的結果。
程式碼
using namespace System;
using namespace System::Collections;
using namespace System::Diagnostics;
using namespace System::Reflection;
ref class HashtableDebugView;
[DebuggerDisplay("{value}", Name = "{key}")]
ref class KeyValuePairs
{
private:
IDictionary^ dictionary;
Object^ key;
Object^ value;
public:
KeyValuePairs(IDictionary^ dictionary, Object^ key, Object^ value)
{
this->value = value;
this->key = key;
this->dictionary = dictionary;
}
};
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(HashtableDebugView::typeid)]
ref class MyHashtable : Hashtable
{
private:
static const String^ TestString = "This should not appear in the debug window.";
internal:
ref class HashtableDebugView
{
private:
Hashtable^ hashtable;
public:
static const String^ TestString = "This should appear in the debug window.";
HashtableDebugView(Hashtable^ hashtable)
{
this->hashtable = hashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState::RootHidden)]
property array<KeyValuePairs^>^ Keys
{
array<KeyValuePairs^>^ get()
{
array<KeyValuePairs^>^ keys = gcnew array<KeyValuePairs^>(hashtable->Count);
IEnumerator^ ie = hashtable->Keys->GetEnumerator();
int i = 0;
Object^ key;
while (ie->MoveNext())
{
key = ie->Current;
keys[i] = gcnew KeyValuePairs(hashtable, key, hashtable[key]);
i++;
}
return keys;
}
}
};
};
public ref class DebugViewTest
{
private:
// The following constant will appear in the debug window for DebugViewTest.
static const String^ TabString = " ";
public:
// The following DebuggerBrowsableAttribute prevents the property following it
// from appearing in the debug window for the class.
[DebuggerBrowsable(DebuggerBrowsableState::Never)]
static String^ y = "Test String";
static void Main()
{
MyHashtable^ myHashTable = gcnew MyHashtable();
myHashTable->Add("one", 1);
myHashTable->Add("two", 2);
Console::WriteLine(myHashTable->ToString());
Console::WriteLine("In Main.");
}
};
int main()
{
DebugViewTest::Main();
}
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
class DebugViewTest
{
// The following constant will appear in the debug window for DebugViewTest.
const string TabString = " ";
// The following DebuggerBrowsableAttribute prevents the property following it
// from appearing in the debug window for the class.
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";
static void Main()
{
MyHashtable myHashTable = new MyHashtable();
myHashTable.Add("one", 1);
myHashTable.Add("two", 2);
Console.WriteLine(myHashTable.ToString());
Console.WriteLine("In Main.");
}
}
[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;
}
}
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
private const string TestString = "This should not appear in the debug window.";
internal class HashtableDebugView
{
private Hashtable hashtable;
public const string TestString = "This should appear in the debug window.";
public HashtableDebugView(Hashtable hashtable)
{
this.hashtable = hashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePairs[] Keys
{
get
{
KeyValuePairs[] keys = new KeyValuePairs[hashtable.Count];
int i = 0;
foreach(object key in hashtable.Keys)
{
keys[i] = new KeyValuePairs(hashtable, key, hashtable[key]);
i++;
}
return keys;
}
}
}
}
Imports System.Collections
Imports System.Diagnostics
Imports System.Reflection
Class DebugViewTest
' The following constant will appear in the debug window for DebugViewTest.
Const TabString As String = " "
' The following DebuggerBrowsableAttribute prevents the property following it
' from appearing in the debug window for the class.
<DebuggerBrowsable(DebuggerBrowsableState.Never)> _
Public Shared y As String = "Test String"
Shared Sub Main()
Dim myHashTable As New MyHashtable()
myHashTable.Add("one", 1)
myHashTable.Add("two", 2)
Console.WriteLine(myHashTable.ToString())
Console.WriteLine("In Main.")
End Sub
End Class
<DebuggerDisplay("{value}", Name:="{key}")> _
Friend Class KeyValuePairs
Private dictionary As IDictionary
Private key As Object
Private value As Object
Public Sub New(ByVal dictionary As IDictionary, ByVal key As Object, ByVal value As Object)
Me.value = value
Me.key = key
Me.dictionary = dictionary
End Sub
End Class
<DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(GetType(MyHashtable.HashtableDebugView))> _
Class MyHashtable
Inherits Hashtable
Private Const TestString As String = "This should not appear in the debug window."
Friend Class HashtableDebugView
Private hashtable As Hashtable
Public Shared TestString As String = "This should appear in the debug window."
Public Sub New(ByVal hashtable As Hashtable)
Me.hashtable = hashtable
End Sub
<DebuggerBrowsable(DebuggerBrowsableState.RootHidden)> _
ReadOnly Property Keys as KeyValuePairs()
Get
Dim nkeys(hashtable.Count - 1) As KeyValuePairs
Dim i as Integer = 0
For Each key As Object In hashtable.Keys
nkeys(i) = New KeyValuePairs(hashtable, key, hashtable(key))
i = i + 1
Next
Return nkeys
End Get
End Property
End Class
End Class