デバッグ中にVisual Studioのコードエディタで変数の上にマウスポインタを移動させると、ツールチップが表示されます。また、デバッガ変数ウィンドウにも変数の情報が表示されます。これらに表示される内容を変更する方法について、ここでは説明します。
例えば、以下の様なクラスがあったとします。
Class SampleClass Private _message As String = "こんにちは。" Public Property Message() As String Get Return Me._message End Get Set(ByVal value As String) Me._message = value End Set End Property Private _words As String() = New String() {"壱", "弐", "参"} Public ReadOnly Property Words() As String() Get Return Me._words End Get End Property End Class
class SampleClass { private string _message = "こんにちは。"; public string Message { get { return this._message; } set { this._message = value; } } private string[] _words = new string[] { "壱", "弐", "参" }; public string[] Words { get { return this._words; } } }
このクラスを使用した以下の様なコードを書き、2行目にブレークポイントを挿入して、デバッグを開始してみます。
Dim c As New SampleClass() '↓の行にブレークポイントがあるものとする Console.WriteLine(c.ToString())
SampleClass c = new SampleClass(); //↓の行にブレークポイントがあるものとする Console.WriteLine(c.ToString());
ブレークポイントで中断中に変数「c」にマウスポインタを置くと、次のようなツールチップ(「c|{SampleClass}」)が表示されます。(ここで紹介している画像はすべてVisual Studio 2010のC#での結果です。)
ここに表示される文字列はToStringメソッドの結果ですので、もし変更したければToStringをオーバーライドします。
例えば以下のようにToStringをオーバーライドしたとします。
Class SampleClass Private _message As String = "こんにちは。" Public Property Message() As String Get Return Me._message End Get Set(ByVal value As String) Me._message = value End Set End Property Private _words As String() = New String() {"壱", "弐", "参"} Public ReadOnly Property Words() As String() Get Return Me._words End Get End Property 'ToStringメソッドをオーバーライドする Public Overrides Function ToString() As String Return String.Format("{0} | {1}", Me.Words.Length, Me.Message) End Function End Class
class SampleClass { private string _message = "こんにちは。"; public string Message { get { return this._message; } set { this._message = value; } } private string[] _words = new string[] { "壱", "弐", "参" }; public string[] Words { get { return this._words; } } //ToStringメソッドをオーバーライドする public override string ToString() { return string.Format("{0} | {1}", this.Words.Length, this.Message); } }
するとツールチップは次のように表示されるようになります。
しかしToStringをオーバーライドしなくても、DebuggerDisplayAttributeを使用すればこの表示内容を変えることができます。この属性は、.NET Framework 2.0以降で使用できます。
以下にその使用例を示します。
'Imports System.Diagnostics 'DebuggerDisplay属性を適用して、デバッガ変数ウィンドウの表示内容を変える <DebuggerDisplay("{Words.Length} | {Message}")> _ Class SampleClass Private _message As String = "こんにちは。" Public Property Message() As String Get Return Me._message End Get Set(ByVal value As String) Me._message = value End Set End Property Private _words As String() = New String() {"壱", "弐", "参"} Public ReadOnly Property Words() As String() Get Return Me._words End Get End Property End Class
//using System.Diagnostics; //DebuggerDisplay属性を適用して、デバッガ変数ウィンドウの表示内容を変える [DebuggerDisplay("{Words.Length} | {Message}")] class SampleClass { private string _message = "こんにちは。"; public string Message { get { return this._message; } set { this._message = value; } } private string[] _words = new string[] { "壱", "弐", "参" }; public string[] Words { get { return this._words; } } }
このようにすると、ツールチップは以下のように表示されるようになります。ToStringの時と違い、全体が { } で囲まれなくなり、逆に文字列は " " で囲まれます。
「{Words.Length}」と「{Message}」は、この箇所にWordsのLengthプロパティとMessageプロパティを表示することを意味します。この { } 内には、フィールド、プロパティ、メソッドの名前を記述できます。また、{ } 内に簡単な式を記述することもできます。
ツールチップの表示だけでなく、デバッガ変数ウィンドウの表示も変化しています。何もしていないSampleClassは、デバッガ変数ウィンドウでは次のように表示されます。なおデバッガ変数ウィンドウを表示するには、デバッグ中にVisual Studioのメニューで[デバッグ]-[ウィンドウ]-[自動変数]などを選択してください。
SampleClassにDebuggerDisplay属性を適用すると、以下のように「値」が変化します。
さらにDebuggerDisplay属性で、デバッガ変数ウィンドウの「名前」と「型」を変更することもできます。以下の例では、値にWordsのLengthプロパティ、名前にMessageプロパティ、型に「サンプル」と表示されるようにしています。
'Imports System.Diagnostics <DebuggerDisplay("{Words.Length}", Name := "{Message}", Type := "サンプル")> _ Class SampleClass Private _message As String = "こんにちは。" Public Property Message() As String Get Return Me._message End Get Set(ByVal value As String) Me._message = value End Set End Property Private _words As String() = New String() {"壱", "弐", "参"} Public ReadOnly Property Words() As String() Get Return Me._words End Get End Property End Class
//using System.Diagnostics; [DebuggerDisplay("{Words.Length}", Name = "{Message}", Type = "サンプル")] class SampleClass { private string _message = "こんにちは。"; public string Message { get { return this._message; } set { this._message = value; } } private string[] _words = new string[] { "壱", "弐", "参" }; public string[] Words { get { return this._words; } } }
このようにすると、デバッガ変数ウィンドウには以下のように表示されるようになります。以下の画像はC#でのもので、名前は変更されませんでした。しかしVB.NETでは名前も変更されました。
補足:DebuggerDisplay属性は、クラス以外に、構造体、デリゲート、列挙体、フィールド、プロパティ、アセンブリに適用できます。
ツールチップやデバッガ変数ウィンドウでは、変数名の左に表示される「+」をクリックすることで、そのオブジェクトのメンバの情報を表示させることができます。
例えば、何もしていないSampleClassクラスでは、次のように表示されます。
DebuggerBrowsableAttributeを使うと、デバッガ変数ウィンドウに表示しないメンバを指定することができます。この属性は、.NET Framework 2.0以降で使用できます。また、.NET Framework 2.0のVB.NETではサポートされていません。
SampleClassクラスでプライベートフィールドをデバッガ変数ウィンドウに表示しないようにした例を以下に示します。
'Imports System.Diagnostics Class SampleClass 'デバッガウィンドウに表示しない <DebuggerBrowsable(DebuggerBrowsableState.Never)> _ Private _message As String = "こんにちは。" Public Property Message() As String Get Return Me._message End Get Set(ByVal value As String) Me._message = value End Set End Property 'デバッガウィンドウに表示しない <DebuggerBrowsable(DebuggerBrowsableState.Never)> _ Private _words As String() = New String() {"壱", "弐", "参"} Public ReadOnly Property Words() As String() Get Return Me._words End Get End Property End Class
//using System.Diagnostics; class SampleClass { //デバッガウィンドウに表示しない [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string _message = "こんにちは。"; public string Message { get { return this._message; } set { this._message = value; } } //デバッガウィンドウに表示しない [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string[] _words = new string[] { "壱", "弐", "参" }; public string[] Words { get { return this._words; } } }
DebuggerBrowsable属性を使用して、配列やコレクションのルートを表示しないようにすることもできます。
SampleClassクラスを以下のように書き換えたとします。
'Imports System.Diagnostics Class SampleClass Private _message As String = "こんにちは。" Public Property Message() As String Get Return Me._message End Get Set(ByVal value As String) Me._message = value End Set End Property Private _words As String() = New String() {"壱", "弐", "参"} '配列のルート要素を表示しない <DebuggerBrowsable(DebuggerBrowsableState.RootHidden)> _ Public ReadOnly Property Words() As String() Get Return Me._words End Get End Property End Class
class SampleClass { private string _message = "こんにちは。"; public string Message { get { return this._message; } set { this._message = value; } } private string[] _words = new string[] { "壱", "弐", "参" }; //配列のルート要素を表示しない [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public string[] Words { get { return this._words; } } }
すると以下のように「Words | {string[3]}」という項目がなくなり、Wordsプロパティの要素があたかもSampleClassの要素のように表示されます。よってこの属性はインデクサに使われることが多いです。
DebuggerTypeProxyAttributeを使えば、全く別のクラス(型の表示プロキシ)のメンバをあたかもそのクラスのメンバのように、デバッガ変数ウィンドウに表示することができます。これを使えば、かなり柔軟にメンバの表示内容を変更することができます。この属性も、.NET Framework 2.0以降で使用できます。
以下の例では、表示プロキシとしてSampleClassDebugViewクラスを作成して、Messageプロパティはそのまま表示し、Wordsプロパティはコンマ区切りで表示されるようにしています。
'Imports System.Diagnostics '型の表示プロキシにSampleClassDebugViewを指定する <DebuggerTypeProxy(GetType(SampleClass.SampleClassDebugView))> _ Class SampleClass Private _message As String = "こんにちは。" Public Property Message() As String Get Return Me._message End Get Set(ByVal value As String) Me._message = value End Set End Property Private _words As String() = New String() {"壱", "弐", "参"} Public ReadOnly Property Words() As String() Get Return Me._words End Get End Property '表示プロキシ Friend Class SampleClassDebugView 'プロキシを使用するオブジェクトを取得する Private _sampleClass As SampleClass Public Sub New(ByVal sc As SampleClass) Me._sampleClass = sc End Sub 'Messageプロパティはそのまま表示する Public ReadOnly Property Message() As String Get Return Me._sampleClass.Message End Get End Property 'Wordsプロパティはコンマ区切りで表示する Public ReadOnly Property Words() As String Get Return String.Join(",", Me._sampleClass.Words) End Get End Property End Class End Class
//using System.Diagnostics; //型の表示プロキシにSampleClassDebugViewを指定する [DebuggerTypeProxy(typeof(SampleClassDebugView))] class SampleClass { private string _message = "こんにちは。"; public string Message { get { return this._message; } set { this._message = value; } } private string[] _words = new string[] { "壱", "弐", "参" }; public string[] Words { get { return this._words; } } //表示プロキシ internal class SampleClassDebugView { //プロキシを使用するオブジェクトを取得する private SampleClass _sampleClass; public SampleClassDebugView(SampleClass sc) { this._sampleClass = sc; } //Messageプロパティはそのまま表示する public string Message { get { return this._sampleClass.Message; } } //Wordsプロパティはコンマ区切りで表示する public string Words { get { return string.Join(",", this._sampleClass.Words); } } } }
このように変更すると、ツールチップは以下のように表示されるようになります。
上の画像はC#でのもので、VB.NETでは異なります。C#では表示プロキシのパブリックメンバしか表示されませんが、VB.NETではプライベートメンバも表示されます。またC#では「列ビュー」という項目で基のオブジェクトのメンバが表示されますが、VB.NETではこの項目が表示されません。
補足:DebuggerTypeProxy属性は、クラス以外に、構造体、アセンブリに適用できます。