今回は前回に引き続き、プログラミングの強力なツールである「デバッガ」について解説します。
前回はブレークポイントとステップ実行の基本について説明しましたが、今回はデバッグにおける「変数値の確認方法」に焦点を当てます。
変数の値を効率的に確認することで、バグの原因特定や動作確認がさらに効率化されます。
この記事では以下について説明します。
- 変数のスコープとは?
- ローカルウィンドウによる変数値の確認
- データヒント機能で素早く値を確認
- 複合型(配列・リスト・クラス)の構造確認
- ウォッチウィンドウでの継続監視
- イミディエイトウィンドウでの変数操作と評価
- デバッグ中に変数値を変更する方法
以下のような方に役立つ内容となっています。
- プログラミング初心者の方、特にC#開発を始めたばかりの方
- Visual Studioのデバッグ機能をさらに深く理解したい方
- プログラムのバグ解決を効率化したいと考えている方
デバッグでは「プログラムのどこが実行されているか」に加え、「ある実行位置で変数の値がどうなっているか」を知ることが重要です。
前回記事では、プログラムのどこが実行されているかにフォーカスしブレークポイント・ステップ実行などの解説をしているので、まずはぜひこちらからご覧ください。

動画は以下になります。
変数値確認の基本
前回記事でもローカルウィンドウで変数値を確認する方法については簡単に説明しました。今回はあらためて基本からみていきましょう。
変数のスコープとは?
変数のスコープとは、コード内でその変数が参照可能な範囲のことです。
C#では主に以下の種類の変数があり、それぞれ異なるスコープを持ちます。
- ローカル変数:メソッドやブロック内で宣言される変数で、宣言されたブロック内でのみ使用可能
- パラメータ変数:メソッドの引数として宣言される変数で、そのメソッド内でのみ使用可能
- インスタンスフィールド:クラス内で宣言され、各オブジェクトインスタンスごとに固有の値を持つ変数
- 静的フィールド(スタティックフィールド):static修飾子が付いたフィールドで、クラスの全インスタンスで共有される変数
デバッグでは、プログラムが停止した時点で「どの変数へアクセスできるか」がスコープによって決まります。
変数の種類や宣言位置を意識しながらデバッグすると効率的です!
ローカルウィンドウで変数を確認
以下の簡単な例で、変数スコープを意識しながらデバッガを用いて様々な変数値を確認してみましょう。
C#コンソールアプリのプロジェクトで、例1としてProgram.csを以下のように用意します。
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
Calculator calc1 = new Calculator();
Calculator calc2 = new Calculator();
// calc1で計算を実行
double result1 = calc1.Add(10, 5);
Console.WriteLine($"計算1の結果: {result1}");
Console.WriteLine($"calc1の最後の結果: {calc1.LastResult}");
// calc2で別の計算を実行
double result2 = calc2.Add(20, 30);
Console.WriteLine($"計算2の結果: {result2}");
Console.WriteLine($"calc2の最後の結果: {calc2.LastResult}");
// 静的フィールドは両方のインスタンスで共有される
Console.WriteLine($"合計操作回数: {Calculator.TotalOperations}");
}
}
internal class Calculator
{
// インスタンスフィールド - 各Calculatorインスタンスごとに固有の値を持つ
public double LastResult = 0;
// 静的フィールド - すべてのCalculatorインスタンスで共有される
public static int TotalOperations = 0;
public double Add(double a, double b)
{
// パラメータ変数 a, b - このメソッド内でのみ使用可能
// ローカル変数 - このメソッド内でのみ使用可能
double sum = a + b;
// インスタンスフィールドを更新
LastResult = sum;
// 静的フィールドを更新
TotalOperations++;
return sum;
}
}
}
このコードでは、CalculatorクラスはインスタンスフィールドとしてLastResult
(最後の計算結果を保持する)を持ちます。
加えて、静的フィールドとしてTotalOperations
(全インスタンスで共有される操作回数のカウンター)を持っています。
例えば、Addメソッド内の「return sum;」の行にブレークポイントを設定し、プログラムを停止させてみましょう。
以下のように、初回は「calc1.Add(10, 5)」のメソッド呼び出し時に停止し、パラメータ変数とローカル変数を確認できます。
メニューの「デバッグ>ウィンドウ>ローカル」で、変数値を確認するんだったね!

Addメソッドの引数はa、bだよね。パラメータ変数の「this」って何?
thisはAddメソッド呼び出し時のインスタンス(calc1)を指しています。thisはインスタンスメソッドで暗黙的に存在するパラメータ変数なのです。
インスタンスメソッド内ではパラメータ変数this経由でインスタンスフィールドへアクセスできます。
以下のようにローカルウィンドウで、thisの部分を展開するとインスタンスフィールドLastResultの値を確認できます。
更に、thisの配下に表示されている「静的メンバー」を展開すると、インスタンスのクラス型(ここではCalculatorクラス)の静的フィールドも確認できます。

このように、デバッガを使うとプログラム停止位置のスコープにおける様々な変数の値を確認できます。
「現在の場所から参照できる変数」が一目でわかるんだね!
フィールド変数などオブジェクト指向の基本については以下の記事も参考にしてください。

データヒント機能で素早く変数値を確認
コード上の変数にマウスカーソルを合わせることで、その変数の現在の値をポップアップで確認できます。これを「データヒント」と呼びます。
プログラムを停止させた時点のスコープに含まれるすべての変数値を確認できます。
さきほどの例で、プログラムを停止させた状態でLastResultへマウスカーソルをあてると、データヒントとして15という値を素早く確認できます。

複合型(配列・リスト・クラス)の値確認方法
単純な数値や文字列だけでなく、複合型のデータ構造の中身も確認できます。例2として、以下のコードを例に見てみましょう。
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
// 配列の例
int[] numbers = { 1, 2, 3, 4, 5 };
// リストの例
List<string> names = new List<string> { "田中", "鈴木", "佐藤" };
// クラスインスタンスの例
Person person = new Person { Name = "山田太郎", Age = 30 };
// 複合データ構造の例
Dictionary<string, int> scores = new Dictionary<string, int>
{
{ "国語", 85 },
{ "数学", 90 },
{ "英語", 75 }
};
Console.WriteLine("デバッグポイント");
Console.ReadLine();
}
}
internal class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
}
「Console.WriteLine(“デバッグポイント”);」の行にブレークポイントを設置し、デバッグ実行すると、ローカルウィンドウで複合型のデータを展開して中身を確認できます。
配列やリストは、展開アイコン(▶)をクリックすることで、各要素の値を確認できます。クラスやオブジェクトも同様に展開でき、プロパティの値を確認できます。

複雑なデータ構造でも、関心のある箇所を展開していくことで詳細に中身の値を確認できるんだね!
特に複雑なデータ構造でのバグ発見には欠かせない機能です。値が正しく設定されているか、想定通りの構造になっているかをすぐに確認できます。
もう一歩進んだ変数値確認
ウォッチウィンドウで特定の変数を継続監視
ウォッチウィンドウは、特定の変数や式を継続的に監視するための機能です。
通常のローカルウィンドウとは異なり、プログラムを停止させたときにスコープに存在する変数や式(単純な変数だけでなく複雑な計算式も含む)の値を表示できます。
例1のコードのブレークポイント停止位置において、ローカルウィンドウで監視したい変数を選択し、右クリックで「ウォッチの追加」を選びます。

以下のようにウォッチウィンドウがデバッグ中に常時表示され、プログラム停止時にその変数がスコープ内であれば、そのときの変数値を確認できます。

特に注目したい変数の変化を効率的に追跡できるんだね。
複数の変数を登録することも可能です。
あと、変数値だけではなく「x.GetTotal()」などの式を設定し、その計算結果を監視することもできます。
イミディエイトウィンドウでの変数操作と評価
イミディエイトウィンドウは、デバッグ中に式を評価したり、変数の値を確認したりするための対話型ウィンドウです。
メニューの「デバッグ>ウィンドウ>イミディエイト」から開くことができます。
イミディエイトウィンドウでは、以下のようなことが可能です。
- 変数の値を表示する:変数名を入力してEnterキーを押すと、その変数の現在の値が表示されます
- 式を評価する:「a + b」などの式を入力して結果を確認できます
- メソッドを呼び出す:「person.GetFullName()」などのメソッド呼び出しも可能です
例えば、先ほどの例2のコードでプログラムを停止した状態で、イミディエイトウィンドウに以下のように入力してみましょう。

「names.Count」と入力してEnterを押すと、リストの要素数「3」が表示されます。
また、「names.Contains(“田中”)」を入力すると、「true」と表示されます。
計算式の結果をすぐに確認できるから、アプリ動作のデバッグに便利だね!
アプリの修正・再実行をせず、その場で「もしこれを実行したらどのような値になるか?」という仮説検証に使えて便利ですね。
デバッグ中に変数値を変更して動作検証
Visual Studioデバッガでは、プログラムの実行を停止した状態で変数の値を変更し、その後の動作を検証することができます。
これにより「もし変数の値がこうだったら」という仮説を簡単にテストできます。変数値の変更方法は主に次の2つです。
- ローカルウィンドウやウォッチウィンドウで直接編集する
- イミディエイトウィンドウで代入式を使用する
①の方法では、ローカルウィンドウやウォッチウィンドウで変数の「値」セルをダブルクリックして新しい値を入力し、Enterキーを押すことで変数値を更新します。
以下は例2のコードで、numbers[ 2 ]の要素を3から30へ変更しています。

②の方法では、イミディエイトウィンドウで代入を行います。

実行中のプログラムの値を変えられるなんてすごい!
これもアプリの修正・再実行をせず、その場で「もしこのような値だったら…」という仮説検証に使えるわけですね。
変数値と連動した条件付きブレークポイント
通常のブレークポイントは設定した行が実行されるたびにプログラムを停止させるのでしたね。
特定の条件が満たされた場合にのみ停止させたい場合は「条件付きブレークポイント」が便利です。
条件付きブレークポイントは以下のように設定します。
- 通常通りブレークポイントを設定
- ブレークポイントを右クリックして「条件…」を選択
- 表示されるダイアログで条件式を入力
例えば、例1のコードのAdd
メソッド内で「double sum = a + b;」の行で、a
が20以上の場合にのみ停止させたい場合は以下に設定します。

以下のように条件を追加しましょう。

以下のように条件付きブレークポイントができました。

こうすると、Add(10, 5)
の呼び出し時には停止せず、Add(20, 30)
の呼び出し時のみ停止します。
条件式には以下のようなものが使えます。
- 変数の値の確認:
a > 10
- 複合条件:
a > 10 && b < 5
- メソッド呼び出し:
names.Count > 2
- オブジェクトのプロパティ:
person.Age >= 20
特定のケースだけで停止させたいときに便利だね!しかも条件式も色々と使えるんだ!
そうですね。特に大量のデータを処理するループの中で、特定の条件のデータだけを調査したいときに重宝しますね。
まとめ
本記事では、Visual Studioの「デバッガ」における変数値の確認方法について詳しく解説しました。
デバッガでの変数値確認には以下のような主要な機能と利点があります。
- ローカルウィンドウによる変数スコープの確認:メソッド内のローカル変数やパラメータ変数、インスタンスフィールドなど、様々な変数値を一覧で確認できます
- データヒント機能:コード上の変数にカーソルを合わせるだけで、素早く値を確認できます
- 複合型データの構造表示:配列・リスト・クラスなどの複雑なデータ構造も、展開して詳細に内容を確認できます
- ウォッチウィンドウ:特定の変数や式を継続監視し、プログラム実行中の変化を追跡できます
イミディエイトウィンドウ:実行中に式を評価したり変数値を表示したりすることで、動作検証を効率化できます
また、デバッグ中に変数値を直接変更したり、条件付きブレークポイントを設定したりすることで、「もしこうだったら」という仮説検証も簡単に行えることを学びました。
変数のスコープを理解し、適切なデバッグ機能を使い分けることで、プログラムの動作理解やバグの原因特定が格段に効率化されます。
引き続き、Visual Studioのデバッグ機能を活用して、C#プログラミングをより効率的に進めていきましょう!