ブロック文
複合文と埋め込み文
if 文のように、他の文を内部に含む構造的な文のことを総称して複合文(composite statements)と呼びます。この複合文に埋め込むことができる文を埋め込み文(embedded statement)と呼びます。逆に言えば、埋め込み文を含む文のことを複合文と呼ぶと定義することもできます。
C# において、多くの文は埋め込み文に該当するため if 文の実行対象として組み込むことができます。しかし、ラベル付き文と宣言文は埋め込み文には該当しないため複合文で利用することができません。ラベル文については後述するので、この場ではローカル変数の宣言文で説明します。
if (x) int y = 0; //エラー
上記のコードは if 文の埋め込み文でローカル変数宣言を記述していますが、宣言文は埋め込み文ではないため無効 if 文の実行対象として指定することはできません。
ブロック文で文を束ねる
if 文の条件によって実行される処理で、新しいローカル変数宣言や複数の文を実行する場合、単一の埋め込み文だけでは表現できません。
if (isReady) System.Console.WriteLine("ARE YOU READY!!"); System.Console.WriteLine("I'M LADY!!");
上記のコードは if 文の実行対象となる埋め込み文をインデントしていることで、視覚上はうまく機能するように見えてしまいます。しかし、if 文の処理対象となるのは最初の文だけです。isReady 変数の状態にかかわらず、文字列 "I'M LADY!!" は出力されるでしょう。
複数の文を if 文の処理対象とするにはブロック文(block statement)を用います。
{ 文のリスト }
ブロック文は中括弧 { } の中に、任意の数だけ文を記述することができる文のコンテナ(入れ物)として機能します。ここには、ラベル文や宣言文を含む任意の文を書くことができるため、埋め込み文のような制約はありません。そして、ブロック文は埋め込み文なので if 文のような複合文の処理対象として記述できます。
if (x) { //任意の文... }
上のコードが if 文の処理対象にブロック文を指定した例です。慣例で、ブロック文の中に記述する文はインデントを 1 段階深くします。
class Test { static void Main() { bool isReady = true; if (isReady) { System.Console.WriteLine("ARE YOU READY!!"); System.Console.WriteLine("I'M LADY!!"); } else { System.Console.WriteLine("ALREADY!!"); System.Console.WriteLine("WE'RE ALL LADY!!"); } } }
コード1は bool 型の isReady 変数によって処理の流れが変わる簡素なプログラムですが if 文や else 部分に指定する埋め込み文にブロック文を指定しています。ブロック文は複数の文を内包するため、if 文の条件によって複数の文を実行できます。
ブロック文とスコープ
ローカル変数には、変数を利用できる有効範囲が存在します。変数の有効範囲のことをスコープ(Scope)と呼び、スコープの外から変数を参照することはできません。スコープから抜け出した時点で、変数の値は破棄されます。
ローカル変数のスコープは、変数が宣言されたブロックの範囲に一致します。メソッドの直下で宣言した場合、そのメソッドのブロック全体で変数は有効です。しかし、ブロック文の中でローカル変数を宣言すると、そのブロック文の中が変数のスコープとなります。すなわち、ブロック文の外から、ブロック文の内側で宣言されたローカル変数にアクセルすることはできません。
{ int i = 100; System.Console.WriteLine("i=" + i); } System.Console.WriteLine("i=" + i); //エラー
上記のコードはブロック文を抜けた後に、ブロック文の中で宣言されている i 変数を利用しようとしています。しかし int 型の i 変数のスコープはブロック文の内側なので、このコードはコンパイルエラーとなります。