System.Diagnostics名前空間にはIDEでのデバッグ操作を支援するための属性が存在します。 ここではそのうちのいくつかを紹介します。

DebuggerDisplay属性

DebuggerDisplay属性は、変数をポイントしたときやウォッチウィンドウに表示されるテキストのフォーマットを指定するための属性です。

using System;
using System.Diagnostics;

[DebuggerDisplay("RGB({R}, {G}, {B}), Alpha = {A}")]
struct ARGB {
  byte R;
  byte G;
  byte B;
  byte A;

  public ARGB(byte r, byte g, byte b, byte a)
  {
    R = r;
    G = g;
    B = b;
    A = a;
  }

  public override string ToString()
  {
    return string.Format("R={0}, G={1}, B={2}, A={3}", R, G, B, A);
  }
}

class Sample {
  static void Main()
  {
    ARGB col = new ARGB(0xff, 0x80, 0x00, 0x80);

    Console.WriteLine(col);
  }
}
Imports System
Imports System.Diagnostics

<DebuggerDisplay("RGB({R}, {G}, {B}), Alpha = {A}")> _
Structure ARGB
  Dim R As Byte
  Dim G As Byte
  Dim B As Byte
  Dim A As Byte

  Public Sub New(ByVal r As Byte, ByVal g As Byte, ByVal b As Byte, ByVal a As Byte)
    Me.R = r
    Me.G = g
    Me.B = b
    Me.A = a
  End Sub

  Public Overrides Function ToString() As String
    Return String.Format("R={0}, G={1}, B={2}, A={3}", R, G, B, A)
  End Function
End Structure

Class Sample
  Shared Sub Main()
    Dim col As New ARGB(&hff, &h80, &h00, &h80)

    Console.WriteLine(col)
  End Sub
End Class

DebuggerDisplay属性が適用されると、デバッグ時にはそのコンストラクタに指定されたフォーマットで表示されるようになります。 このコードをビルドし、デバッグモードでステップ実行しながら変数colをポイントしたりウォッチウィンドウに追加すると、"RGB(255, 128, 0), Alpha = 128"のように表示されるようになります。 オーバーライドしたToString()が返す値とは異なる点に注目してください。

この例では構造体にDebuggerDisplay属性を適用していますが、クラスや列挙型、プロパティ・フィールドなどにも適用することができます。 また、この例では単純にフィールドの値を表示しているだけですが、簡単な条件式やメソッド呼び出しの結果を表示させるようにすることも出来ます。 詳しくはDebuggerDisplay 属性の使用を参照してください。

DebuggerStepThrough属性

DebuggerStepThrough属性は構造体、クラス、メソッド、コンストラクタに対して適用し、適用された要素はデバッグ時にステップ・インしなくなります。 例えば次のコードのDebuggerMethod()メソッドの中にブレークポイントを設定し、メソッドにステップ・インしようとしても、ステップ・インせずにメソッドの処理が終了し、メソッド呼び出しのあった次の行に進むようになります。

using System;
using System.Diagnostics;

class Sample {
  [DebuggerStepThrough]
  static void DebuggedMethod()
  {
    // デバッグ済みのコードがあるとする
    Console.WriteLine("処理が完了しました。");
  }

  static void Main()
  {
    DebuggedMethod();
  }
}
Imports System
Imports System.Diagnostics

Class Sample
  <DebuggerStepThrough> _
  Shared Sub DebuggedMethod()
    ' デバッグ済みのコードがあるとする
    Console.WriteLine("処理が完了しました。")
  End Sub

  Shared Sub Main()
    DebuggedMethod()
  End Sub
End Class

このように、バグの原因を探すために一行ずつ実行するときにデバッグ済みのコードも一行ずつ実行しなければならないのは非常に不便なので、デバッグが完了したメソッドやクラスにDebuggerStepThrough属性を適用することでデバッグ対象から外すことができ、効率的なデバッグが行えるようになります。

ただし、一行ずつ実行することはできなくても、ブレークポイントを設定することができ、実行時には設定されたところで停止します。 また言うまでもありませんが、リリースビルドではDebuggerStepThrough属性を指定していようといなかろうと無関係です。

DebuggerHidden属性

DebuggerHidden属性はDebuggerStepThrough属性と似た属性で、メソッド及びプロパティに対して使用します。 ただDebuggerStepThrough属性とは異なり、使用されたメソッドの中にブレークポイントを設定することはできても、デバッグ時にはその要素が見えなくなり、ブレークポイントが到達してもそのメソッドの外部(=呼び出し元)で停止します。

using System;
using System.Diagnostics;

class Sample {
  [DebuggerHidden]
  static void DebuggedMethod()
  {
    // デバッグ済みのコードがあるとする
    Console.WriteLine("処理が完了しました。");
  }

  static void Main()
  {
    DebuggedMethod();
  }
}
Imports System
Imports System.Diagnostics

Class Sample
  <DebuggerHidden> _
  Shared Sub DebuggedMethod()
    ' デバッグ済みのコードがあるとする
    Console.WriteLine("処理が完了しました。")
  End Sub

  Shared Sub Main()
    DebuggedMethod()
  End Sub
End Class

DebuggerNonUserCode属性

DebuggerNonUserCode属性はDebuggerStepThrough属性とDebuggerHidden属性を組み合わせたような属性です。 この属性が適用されると、デバッグ時にはその要素が見えなくなり、またステップ・インしなくなります。
通常は、IDEが自動的に生成した非ユーザーコード・デザイナーのコードなどをデバッガ上から隠すためにこの属性が用いられますが、独自のコードにもこの属性を適用することは出来ます。

using System;
using System.Diagnostics;

class Sample {
  [DebuggerNonUserCode]
  static void HiddenProcess()
  {
    // デバッガで表示する必要のないコードがあるとする
    Console.WriteLine("処理が完了しました。");
  }

  static void Main()
  {
    HiddenProcess();
  }
}
Imports System
Imports System.Diagnostics

Class Sample
  <DebuggerNonUserCode> _
  Shared Sub HiddenProcess()
    ' デバッガで表示する必要のないコードがあるとする
    Console.WriteLine("処理が完了しました。")
  End Sub

  Shared Sub Main()
    HiddenProcess()
  End Sub
End Class