ここではVB.NETの繰り返し(ループ)ステートメントについて見ていきます。 VB.NETには、
- 初期値・終了値・増分を指定して繰り返すFor-Nextステートメント
- 配列・コレクションの各要素一つずつに対して繰り返すFor-Each-Nextステートメント
- 条件式が成り立っている間繰り返すWhileステートメント
- 条件式が成り立つまで(成り立っている間)繰り返すDo-Loopステートメント
の4つのループ構文が用意されています。 またExit
によってループの中断、Continue
によってループのスキップを行うことができます。
For-Nextステートメント
Forステートメントは繰り返す回数が決まっている場合に使用します。 Forステートメントでは今何回繰り返したかを覚えておくためのカウンタ変数が必要になります。 構文の形式は次の通りです。
この構文のうち [ ]でくくった部分は省略可能な部分です。
Forステートメントでは、まずカウンタ変数を初期値に指定し、増分で指定した分ずつカウンタ変数の値を増やしていきます。 その度にForから Nextの間に記述されているすべてのステートメントを実行します。 カウンタ変数が終了値に達するか越えた場合、繰り返しが終了します。 このとき増分を省略すると増分は1とされます。
ForステートメントではForステートメントの中にさらにForステートメントを含めることもできます。 この場合、内側のForステートメントから順に繰り返されていきます。
VB.NET 2003 (Visual Studio .NET 2003)からは、次の例のようにForステートメントで使用できるカウンタ変数をForステートメント内で宣言できるようになりました。
このようにして宣言したカウンタ変数は、Forステートメント内のみで有効であることに注意してください。 この例の変数iはForステートメントの外から参照することはできません。 カウンタ変数のスコープについてはブロックと変数のスコープも参照してください。
Nextの後ろには対応するForのカウンタ変数を記述することが出来ます。 これは本来省略可能なものですが、多重ループなどの内側の処理が長くなる場合などでは、カウンタ変数を記述することでForステートメントとカウンタ変数の対応が分かりやすくなるようにすることが出来ます。
For-Each-Nextステートメント
For-Eachステートメントは配列など特定の要素の集まり(コレクション)に対して、そのすべての要素を順番に一つずつ抜き出しながら繰り返す場合に使用します。 For-Eachステートメントでは抜き出した要素を扱うための変数を用意しておく必要があり、その変数の型は当然要素を格納できる型である必要があります。 構文の形式は次の通りです。
For-EachステートメントはForステートメントをより簡単にしたようなものなので動作は容易に予想できると思います。 次のコードは配列に含まれるすべての要素を抜き出して表示するコードです。
二次元配列に対してFor-Eachステートメントを使用した場合も、一次元配列と同様に1つずつ要素が抜き出されます。
Forステートメント同様、For-EachステートメントでもVB.NET 2003 (Visual Studio .NET 2003)からは、ステートメント内で使用できる要素変数をステートメント部で宣言できるようになりました。
配列・多次元配列の宣言・作成については配列、二次元以上の配列の扱い方については多次元配列・ジャグ配列で解説しています。
For-Eachステートメントで列挙できるもの、列挙するために必要な要件、そして列挙する際の動作などはIEnumerable・IEnumeratorで詳しく解説しています。
While-End Whileステートメント
Whileステートメントは繰り返す回数ではなく、繰り返しを続ける(または、やめる)条件が決まっている場合に使用します。 構文の形式は次の通りです。 VB.NETでは他のブロック構造との整合性を保つためにWendキーワードは使用せず、代わりにEnd Whileを使わなければなりません。
この条件式が成り立っている限り(式が真である限り)繰り返されます。 条件が常に成り立ってしまうようにコーディングすると無限ループしてしまうので注意が必要です。 意図的に無限ループにすることもありますが、その場合でも通常はループを中止するためのコードを記述します。
比較のため、Forステートメントを使って上記のコードと同様の動作をするコードを記述すると次のようになります。
条件式の記述方法についてはIf Then Elseステートメントを参照してください。
Do-Loopステートメント
Do-LoopステートメントはWhileステートメントと似ていますが、Whileとは異なり様々なバリエーションの条件を付けることができます。 その構文を次に示します。
次の例は、Do-Loop Untilを使った繰り返しの例です。
次の例は、上記の例をDo While-Loopを使って書き換えた例です。
これは、While-End Whileを使って次のように記述する事もできます。
While 条件式、 Until 条件式で条件式を記述しない場合でも、Exitステートメントを使用することでループを中断することができます。
無限ループ
Do-Loopステートメントでは条件式を省略することができ、これを省略すると無限ループとなります。 Do-Loopステートメントを使えばもっともシンプルに無限ループを記述できます。
C言語で無限ループを記述するのに使われるwhile(1) {...}
をVBで記述する場合は、While-End Whileステートメントが使えます。 条件式が常に真となれば無限ループとなるので、次の例ではTrue
を使っています。
もう一つ、C言語で使われる無限ループfor(;;) {...}
をVBで記述する場合はFor-Nextステートメントが使えます。 ただし、C言語のfor文ではループの終了条件を記述するのに対しFor-Nextステートメントではループの終了値を記述するという違いがあります。 そのため、次の例ようにStep 0
を指定して終了値に達することがないようにすることでFor-Nextステートメントで無限ループを記述することが出来ます。
Stepを記述しない代わりに、カウンタ変数の値を元に戻すことで終了値に達しないようにすることでも無限ループを記述出来ます。
無限ループを記述する場合でも、ある条件を満たした場合にループを抜けたいという場合には、Exitステートメントを使用します。
ループステートメントの中断とスキップ
Exitステートメント (ループの中断)
ForやWhileなどのステートメントでは、ループの途中でループから抜けることができます。 その場合にはExitステートメントを使います。 これはCやC#のfor文におけるbreakに相当するものです。 ForループではExit For、WhileループではExit Whileのように使います。
入れ子になっているループとExitステートメント
入れ子になっている(ネストされた)ループ構造の中でExitステートメントを実行する場合は、Exitで指定したものに対応するループ構文のうち、最も内側にあるものが中断される点に注意が必要です。 次の例では二重のForステートメントの内側でExit Forステートメントを実行しています。
次の例は、先の例を少し変えて、外側をWhileステートメントにし、Forステートメントの内側でExit Whileステートメントを実行しています。
この例においてExit Whileの代わりにExit Forとすると内側のForのループを中断するようになり、最初に示したコードと同様の動作となります。
Exitステートメントはここで紹介した繰り返し構文の他にも、プロシージャの中断でも使われます。
入れ子になっているループからの脱出
Exitステートメントではもっとも内側にあるExitに対応するループを中断することは出来ますが、Exitステートメントだけでは二重のForループを中断するといったことが出来ません。 入れ子になっているループから脱出する方法にはいくつかありますが、その一つは次のようにフラグとExitステートメントを組み合わせる方法です。
もう一つはExitステートメントの代わりにGoToステートメントを使ってループの外に脱出する方法です。
もし入れ子になっているループ部分をプロシージャとして分離できるなら、次のようにExit Sub/Functionステートメントを使ってプロシージャごと中断することで入れ子になっているループを中断することも出来ます。 次の例ではExit Subステートメントを使っていますが、当然Returnステートメントを使うことも出来ます。
上記の例とTry-Finally-End Tryステートメントを組み合わせることで、プロシージャ終了時に処理を行うようにすることも出来ます。
例外をスローして処理を中断することによりループを脱出する方法も考えられます。 ただし、例外をスローする際のコストや、意図しない例外をキャッチしてしまう可能性等を考慮すると、ループを脱出することだけを目的にして例外をスローするこの方法はあまり推奨できる方法ではありません。
Continueステートメント (ループのスキップ)
VB.NET 2005 (Visual Studio 2005)からはContinueステートメントが使えるようになりました。 Continueステートメントを使うと、ループの途中で残りの処理をスキップし、ループ処理の先頭に戻ることができます。 これはCやC#のfor文におけるcontinueに相当するものです。 Continueステートメントでスキップした場合、Continue以降の処理は実行されなくなります。 Exitステートメントと同様、ForループではContinue For、WhileループではContinue Whileのように使います。
ContinueステートメントもExitステートメントと同様に、Continueステートメントで指定したものに対応するループ構文のうち、最も内側にあるものがスキップされます。