無限ループよ、さらば!VB.NETのDo…LoopとWhile…End While、どっちを使う?〜業務アプリを支える安全な繰り返し処理の設計〜
皆さん、こんにちは!Visual Basic (VB / VB.NET)の世界へようこそ。マクロの記録から一歩踏み出し、自分でコードを書いて業務を自動化したい!そんな熱い思いを胸に、このブログを訪れてくださったあなたへ。温かい拍手をお送りします!
私は、長年VB/VB.NETと共に歩み、数々の業務自動化プロジェクトを成功に導いてきた、いわば「VBの錬金術師」です。今回は、皆さんが必ずと言っていいほどお世話になる「繰り返し処理」について、特に初心者の方がつまずきがちな「無限ループ」を確実に回避し、さらにコードを読みやすくするための極意をお伝えします。
「Do…Loop」と「While…End While」、どちらも繰り返し処理に使うのに、一体何が違うの?どっちを使えばいいの?そんな疑問に、実例を交えながら、優しく、そして深く、お答えしていきますね。ここをクリアすれば、VB.NETの繰り返し処理の基本はバッチリですよ!
繰り返しの基本:なぜ「繰り返し処理」が必要なのか?
皆さんの日々の業務を思い浮かべてみてください。
- 「Aというファイルからデータを100行読み込む」
- 「Bというリストにある全ての項目に対して、Cという処理を実行する」
- 「Dという条件を満たすまで、Eという計算を繰り返す」
これらの作業は、すべて「同じような処理を何度も行う」という特徴を持っています。これを一つ一つ手作業で、あるいはコードをコピペして書くのは、非効率的ですし、間違いも起こりやすいですよね。
そこで登場するのが「繰り返し処理」です。繰り返し処理を使うことで、私たちは「この処理を〇回繰り返してね」「この条件が満たされるまで繰り返してね」とコンピュータに指示でき、作業を劇的に効率化できます。
VB.NETには、主に以下の2つの繰り返し構文があります。
1. Do…Loop 構文
2. While…End While 構文
どちらも繰り返し処理を実現できますが、その「動く仕組み」と「得意な場面」が少し異なります。この違いを理解することが、安全で効率的なコードを書くための第一歩なのです。
1.Do…Loop 構文:柔軟性と「後判定」の安全設計
まずは「Do…Loop」構文から見ていきましょう。この構文は、非常に柔軟性に富んでおり、特に「最低でも1回は処理を実行したい」という場合に威力を発揮します。
Do…Loop の基本形
Do…Loopには、条件を判定するタイミングによっていくつかの形がありますが、今回は特に重要な2つを紹介します。
1. Do While…Loop
この形は、ループの最初で条件を判定します。条件が「真(True)」の間、ループ内の処理が実行されます。
.net
‘ Do While…Loop の例:1から5までを表示する
Dim counter As Integer = 1
Do While counter <= 5 ' ここがループの中で実行される処理です Console.WriteLine($"現在のカウント: {counter}") ' カウンターを1増やす(これを忘れると無限ループ!) counter += 1 Loop Console.WriteLine("Do Whileループが終了しました。") 【解説】
- `Dim counter As Integer = 1`: まず、繰り返しの回数を数えるための変数`counter`を宣言し、初期値として`1`を設定します。
- `Do While counter <= 5`: ここで条件判定です。「`counter`が5以下である」という条件が「真(True)」の間、ループは続きます。
- `Console.WriteLine(…)`: ループの中で実行したい処理です。ここでは、現在の`counter`の値を表示しています。
- `counter += 1`: これが超重要! ループが1回終わるごとに、`counter`の値を1増やしています。この処理がないと、`counter`はずっと`1`のままなので、`counter <= 5`という条件が永遠に真となり、無限ループに陥ってしまいます!
- `Loop`: ここまでが1回の繰り返し処理の範囲であることを示します。
【ポイント】
- 条件判定がループの最初で行われるため、もし最初に条件が「偽(False)」であれば、ループ内の処理は一度も実行されません。
2. Do…Loop While
こちらは、ループの最後で条件を判定します。この構文の最大の特徴は、ループ内の処理が最低でも1回は必ず実行されることです。
.net
‘ Do…Loop While の例:ユーザーに値を入力してもらう(最低1回は入力を求める)
Dim userInput As String = “”
Do
‘ ここがループの中で実行される処理です
Console.Write(“何か文字を入力してください(’quit’で終了): “)
userInput = Console.ReadLine()
Console.WriteLine($”入力された文字: {userInput}”)
‘ ループを続ける条件を最後に判定します
Loop While userInput <> “quit”
Console.WriteLine(“Do…Loop Whileループが終了しました。”)
【解説】
- `Do`: ループの開始を示します。
- `Console.Write(…)` と `userInput = Console.ReadLine()`: ユーザーに何かを入力してもらい、その値を`userInput`変数に格納します。この処理は、条件判定に関わらず、ループの最初に必ず実行されます。
- `Console.WriteLine(…)`: 入力された内容を表示します。
- `Loop While userInput <> “quit”`: ここで条件判定です。「`userInput`が`”quit”`ではない」という条件が「真(True)」の間、ループは続きます。もし最初から`userInput`が`”quit”`だったとしても、`Do`から`Loop While`までの処理は1回実行されます。
【ポイント】
- 条件判定がループの最後で行われるため、ループ内の処理は最低1回は必ず実行されます。
- 「最低1回は実行したい」という要件がある場合に、非常に適しています。例えば、ユーザーに有効な値を入力させるために、最初に入力を促し、その後で入力値が正しいかチェックする、といったシナリオで役立ちます。
Do…Loop の「無限ループ回避」テクニック
Do…Loop構文で無限ループに陥る最も典型的な原因は、ループ内で条件判定に使われる変数の値が、ループが回っても変化しないことです。
【悪い例:無限ループ発生!】
.net
‘ 警告:このコードは無限ループになります!
Dim i As Integer = 0
Do While i < 5
Console.WriteLine("このメッセージは消えません…")
' i += 1 を忘れてしまった!
Loop
このコードでは、`i`の値がずっと`0`のままなので、`i < 5`という条件が永遠に真となり、ループから抜け出せません。
【安全な設計の秘訣】
1. 条件判定に使われる変数は、ループ内で必ず更新する: `Do While`ならループの最後の方で、`Do…Loop While`ならループの最後で、条件判定に使われる変数の値を変化させましょう。
2. 「終了条件」を明確にする: ループがいつ終わるのか、その条件をコードの冒頭でコメントとして明記するのも効果的です。
Do…Loop が向いている場面
- 最低1回は処理を実行したい場合: `Do…Loop While`構文が最適です。
- 処理の回数が事前に決まっていないが、何かしらの処理を試してから条件を判断したい場合: `Do…Loop While`が便利です。
- 柔軟にループの開始・終了条件を設計したい場合: `Do While…Loop`や`Do Until…Loop`(条件が「偽」の間繰り返す)など、様々なバリエーションで対応できます。
2.While…End While 構文:シンプルさと「先判定」の効率性
次に「While…End While」構文を見ていきましょう。こちらは「Do While…Loop」と似ていますが、こちらも「条件判定のタイミング」が重要です。
While…End While の基本形
.net
‘ While…End While の例:1から5までを表示する
Dim counter As Integer = 1
While counter <= 5 ' ここがループの中で実行される処理です Console.WriteLine($"現在のカウント: {counter}") ' カウンターを1増やす(これも忘れると無限ループ!) counter += 1 End While Console.WriteLine("Whileループが終了しました。") 【解説】
- `Dim counter As Integer = 1`: こちらも繰り返し回数を数えるための変数を初期化します。
- `While counter <= 5`: ループの最初で条件判定を行います。「`counter`が5以下である」という条件が「真(True)」の間、ループ内の処理が実行されます。
- `Console.WriteLine(…)`: ループの中で実行したい処理です。
- `counter += 1`: これも超重要! `Do While…Loop`と同様に、この更新処理がないと無限ループに陥ります。
- `End While`: `While`からここまでが1回の繰り返し処理の範囲であることを示します。
【ポイント】
- 条件判定がループの最初で行われます。
- `Do While…Loop`の「`Do While`」とほとんど同じ動作をします。
While…End While の「無限ループ回避」テクニック
`While…End While`構文での無限ループ回避も、`Do While…Loop`の`Do While`の場合と同様に、条件判定に使われる変数がループ内で必ず更新されることが絶対条件です。
【悪い例:無限ループ発生!】
.net
‘ 警告:このコードは無限ループになります!
Dim i As Integer = 0
While i < 5
Console.WriteLine("これも永遠に表示されます…")
' i += 1 を忘れてしまった!
End While
こちらも、`i`の値が更新されないため、`i < 5`が永遠に真となり、無限ループに陥ります。
【安全な設計の秘訣】
1. 条件判定に使用する変数は、ループの各イテレーション(回)で必ず更新する: これが最も基本的かつ重要な原則です。
2. ループの直前に、終了条件を確認する: `While`文の条件式が、ループに入る前に評価されることを意識しましょう。
While…End While が向いている場面
- 条件が満たされている間、処理を繰り返したい場合: `While…End While`は非常に直感的で分かりやすい構文です。
- ループに入る前に、条件を満たしているか確認したい場合: `Do While…Loop`の`Do While`と同様に、条件が偽であればループ内の処理は実行されません。
- コードの意図が「〜の間、続ける」と明確な場合: `While`という単語が、その意図をストレートに表現します。
3.「無限ループ」を絶対に防ぐ!実践的な条件判定テクニック
さて、ここまで`Do…Loop`と`While…End While`の基本的な仕組みを見てきました。どちらの構文でも、無限ループを防ぐには「ループ内で条件判定に使われる変数が必ず更新されること」が重要だとお伝えしました。
しかし、実際の業務アプリケーションでは、もっと複雑な条件が絡むことがよくあります。そんな時に役立つ、無限ループを絶対に回避するための「安全な条件判定」の設計テクニックをいくつかご紹介しましょう。
テクニック1:明確な「終了フラグ」変数の導入
ループの終了条件を管理するため、専用のブール型変数(True/Falseを持つ変数)を用意する方法です。
.net
‘ 終了フラグを使った安全なループ
Dim keepProcessing As Boolean = True ‘ 最初はTrue(処理を続ける)
Dim dataCount As Integer = 0
Const MAX_RECORDS As Integer = 100 ‘ 処理する最大件数
‘ 実際のデータ読み込み処理などを模倣
Dim simulatedData As New List(Of String)()
For i As Integer = 1 To 150
simulatedData.Add($”Data Item {i}”)
Next
Dim recordIndex As Integer = 0
While keepProcessing
‘ — ここからループ内で実行される処理 —
‘ 終了条件のチェック(複数条件をここに記述)
If recordIndex >= simulatedData.Count OrElse dataCount >= MAX_RECORDS Then
keepProcessing = False ‘ 終了フラグをFalseにする
‘ break ‘ ループを強制的に抜けることも可能ですが、フラグで制御する方が可読性が高い場合も
End If
‘ 終了フラグがFalseになったら、以降の処理はスキップ(またはループを抜ける)
If Not keepProcessing Then
Continue While ‘ 次のループイテレーションへ進む (breakの代わり)
End If
‘ 実際のデータ処理(例:1件処理する)
Console.WriteLine($”処理中: {simulatedData(recordIndex)}”)
dataCount += 1
recordIndex += 1
‘ — ここまでループ内で実行される処理 —
End While
Console.WriteLine($”ループ終了。処理件数: {dataCount} 件。”)
【解説】
- `Dim keepProcessing As Boolean = True`: `keepProcessing`という名前のブール型変数を`True`で初期化します。これが「ループを続けるかどうか」を管理するフラグになります。
- `If recordIndex >= simulatedData.Count OrElse dataCount >= MAX_RECORDS Then keepProcessing = False`: ループの内部で、終了条件(データの終端に達した、または最大件数を超えた)をチェックします。条件を満たしたら、`keepProcessing`を`False`にします。
- `If Not keepProcessing Then Continue While`: もし`keepProcessing`が`False`になっていたら、それ以降のループ内の処理を実行せずに、次のループイテレーション(繰り返し)に進みます。`Continue While`は、そのイテレーションだけをスキップして次に進むための命令です。`Exit While`を使えばループ全体を抜けることもできます。
【なぜ安全か?】
- 終了条件が1箇所に集約される: 複数の場所で`counter`をインクリメントする代わりに、`keepProcessing`という1つのフラグでループの生死を制御できます。
- コードの意図が明確になる: `keepProcessing`という名前を見れば、この変数がループの継続を管理していることが一目でわかります。
テクニック2:ループ回数の上限設定
「この処理は、どんなに遅くても〇回まで」という明確な上限がある場合、それをループの終了条件に加えることで、意図しない無限ループを防ぐことができます。
.net
‘ ループ回数の上限を設定する例 (Do…Loop While)
Dim attempts As Integer = 0
Dim maxValue As Integer = 10
Dim currentValue As Integer = 5
Do
Console.WriteLine($”試行回数: {attempts}, 現在の値: {currentValue}”)
‘ 何らかの処理でcurrentValueが変化すると仮定
‘ 例: currentValue = currentValue + System.Convert.ToInt32(Math.Floor(Rnd() 3)) ‘ ランダムに増減
currentValue += 1 ‘ 例として単純に増やす
attempts += 1 ‘ 試行回数をカウントアップ
‘ 終了条件: currentValueがmaxValueを超えた、または試行回数が上限に達した
Loop While currentValue < maxValue AndAlso attempts < 5 ' ここで試行回数上限もチェック!
Console.WriteLine($"ループ終了。最終試行回数: {attempts}, 最終値: {currentValue}")
【解説】
- `attempts As Integer = 0`: 試行回数をカウントする変数を初期化します。
- `attempts < 5`: ループの継続条件に、`attempts`が5未満であることも加えています。
- `attempts += 1`: 毎回のループで試行回数を増やしています。
【なぜ安全か?】
- たとえ`currentValue < maxValue`という条件が永遠に真になり続けたとしても、`attempts < 5`という条件がいつか偽になるため、ループは必ず終了します。
- 特に、外部システムとの連携や、時間がかかる処理で、タイムアウトやリトライ回数を設ける場合に有効です。
4.可読性向上のための「選び方」と「書き方」
さて、無限ループを防ぐためのテクニックがわかったところで、次は「どうすれば、もっとコードが読みやすくなるか?」という点に焦点を当てましょう。
Do…Loop vs While…End While:どちらを選ぶべきか?
これは、「その処理が、最低1回は実行される必要があるかどうか」で判断するのが、最もシンプルで分かりやすい基準です。
- 最低1回は実行したい → `Do…Loop While`
- 例:ユーザーに何か入力してもらい、その入力が有効かチェックする。最初に入力を促す処理は必ず必要です。
- 条件が満たされない場合は、一度も実行したくない → `While…End While` または `Do While…Loop`
- 例:リストにデータがある間だけ処理を続ける。リストが空なら、何もせずに終わってほしい。
「`Do While…Loop`」と「`While…End While`」は、動作としては非常に似ています。どちらを使っても構いませんが、コードを見たときに、その処理の意図がすぐに伝わる方を選ぶのが良いでしょう。一般的には、`While…End While`の方が「〜の間」というニュアンスが強く、シンプルに条件が満たされている間だけ繰り返す、という意図が伝わりやすいかもしれません。
可読性を高める!コードの書き方テクニック
1. 変数名に意味を持たせる: `i`や`j`のような単調な名前も使われますが、特にループの回数や条件に関わる変数には、`recordCount`、`maxAttempts`、`isFinished`のように、その変数が何を表しているのかがわかる名前をつけましょう。
2. ループの目的をコメントで明記する: ループの直前に、そのループが何をするためのものなのか、どのような条件で終了するのかをコメントで記述します。
.net
‘ ////////////////////////////////////////////////////////////////
‘ // ファイルからデータを読み込み、処理するループ
‘ // 終了条件:ファイルの終端に達するか、エラーが発生した場合
‘ ////////////////////////////////////////////////////////////////
While Not fileStream.EndOfStream
‘ … ファイル読み込み処理 …
End While
3. インデントを正しく使う: コードブロック(ループの中身など)は、必ずインデント(字下げ)を正しく行いましょう。これにより、コードの構造が視覚的に分かりやすくなります。IDE(統合開発環境)は自動でインデントしてくれるので、意識して使いましょう。
4. 長すぎるループは避ける: もしループ処理が何十行、何百行にも及ぶ場合は、そのループ処理を別のメソッド(関数)に切り出すことを検討しましょう。これにより、元のコードがスッキリし、可読性が向上します。
まとめ:VB.NETの繰り返し処理マスターへの道
お疲れ様でした!今回は、VB.NETの繰り返し処理の基本である`Do…Loop`と`While…End While`について、その動作特性の違いから、業務アプリで最も恐ろしい「無限ループ」を回避するための具体的なテクニック、そしてコードを読みやすくするための工夫まで、じっくりと解説しました。
- `Do…Loop`: 特に`Do…Loop While`は、最低1回は処理を実行したい場合に最適。
- `While…End While`: 条件が満たされている間だけ処理を繰り返したい場合に直感的で分かりやすい。
- 無限ループ回避の鉄則: ループ内で、条件判定に使われる変数は必ず更新すること!
- 安全な設計: 明確な「終了フラグ」の導入や、「ループ回数の上限設定」は強力な武器になります。
- 可読性向上: 意味のある変数名、的確なコメント、正しいインデントを心がけましょう。
これらの知識をしっかりと身につければ、皆さんは「無限ループの悪夢」に悩まされることなく、自信を持って繰り返し処理を使いこなせるようになります。そして、それは皆さんの業務アプリケーション開発の質を劇的に向上させるはずです。
もし、コードを書いている途中で「あれ?このループ、ちゃんと終わるかな?」と不安になったら、今回お伝えした「終了フラグ」や「回数上限設定」のテクニックを思い出してください。きっと、安全で堅牢なコードを書く手助けをしてくれるはずです。
さあ、あなたもVB.NETの繰り返し処理マスターへの道を歩み始めましょう!応援しています!
