【実務・中級編】VB.NETにおけるDo…LoopとWhile…End Whileの使い分け:無限ループを回避し可読性を高めるループ制御の鉄則 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

【VB.NET極意】Do…LoopとWhile…End Whileの使い分け:無限ループを回避しバグゼロを実現するループ制御の鉄則

こんにちは。チーフアーキテクトの私だ。
これまで数多の基幹システムや、現場の泥臭い業務自動化ツールを見てきたが、いまだに信じられないバグに遭遇することがある。その最たるものが「意図せぬ無限ループ」「1回は動くべきなのに動かない幽霊ループ」だ。

VB.NETには、条件付きループを構築するための構文として `While…End While` と `Do…Loop` が存在する。
「どちらを使っても同じだろう」などと安易に考えていないか?

結論から言おう。この2つの構文の選定を誤ることは、コードの寿命を縮め、将来のバグの温床を作る自殺行為に等しい。 特にファイルストリームの読み込みやデータベースのバッチ処理において、この選択ミスは致命的なメモリリークやフリーズを引き起こす。

今回は、プロの現場で通用する「絶対に事故らないループ制御の極意」を叩き込む。

1. 脳裏に刻め:前置判定と後置判定の決定的な違い

ループ構文の本質は「いつ条件を評価するか」だ。

  • 前置判定 (Pre-test): ループに入る前に条件を評価する。条件が不成立なら、中身は1回も実行されない
  • 後置判定 (Post-test): ループの最後に条件を評価する。条件がどうあれ、中身は最低1回は必ず実行される

この原則を踏まえ、各構文の特性を見ていこう。

2. While…End While:厳格な「前置判定」の守護神

`While…End While` は、純粋な前置判定の構文だ。

.net
While 条件式
‘ 処理
End While

【特性とユースケース】

  • 特徴: 条件を満たさない限り、内部のコードは1バイトたりとも実行されない。
  • 最適な場面: 「処理を行う前に、前提条件が確実に満たされている必要がある場合」。
  • 例:設定ファイルが存在する場合のみ読み込み処理を開始する。
  • 例:残高がプラスの期間だけ計算を回す。

【危険な罠】

もしループ内で条件を変化させる変数をインクリメントし忘れたり、例外処理でループ脱出ロジックがバイパスされたりすると、即座に無限ループの完成だ。UIスレッドでこれをやらかすと、アプリは「応答なし」となり、ユーザーの怒りを買うことになる。

3. Do…Loop:変幻自在の万能選手(前置・後置の選択)

`Do…Loop` は、VB.NETのループ制御における真の主役である。`While` や `Until` を前置・後置のどちらにも配置できるため、表現力が圧倒的に高い。

パターンA:Do While…Loop(前置判定)

`While…End While` とほぼ同義だが、VBの伝統的な構文。

.net
Do While 条件式
‘ 処理
Loop

パターンB:Do…Loop While(後置判定)

「まずは絶対に1回実行し、その結果を見て継続を判断する」という現場で最も頻出するパターン。

.net
Do
‘ 処理(最低1回は実行される)
Loop While 条件式

4. 【実務の現場から】ファイルストリーム読み込みにおける鉄則

理論はこの辺りにして、実務で最も差が出る「テキストファイルの行単位読み込み(StreamReader)」を題材に、正しい設計を見せよう。

❌ やってはいけないアンチパターン(可読性の低いコード)

ファイルの終端(EOF)チェックを誤り、無限ループや予期せぬ挙動を生む典型例だ。

.net
‘ 【悪手】Whileで無理やり書いた例。読みにくい上に条件が分散しやすい。
Dim reader As New System.IO.StreamReader(“C:\data\log.txt”)
Dim line As String = reader.ReadLine()

While line IsNot Nothing
Console.WriteLine(line)
line = reader.ReadLine() ‘ 読み込み忘れや順序ミスが起きやすい
End While
reader.Close()

⭕ プロダクションコード:`Do…Loop` と `Exit Do` による堅牢な設計

ファイル読み込みやバッチ処理では、「無限ループの形をあらかじめ作り、内部で安全に離脱(Exit Do)する」のが最もバグが少なく、保守性が高い。

.net
Imports System.IO

Public Class LogProcessor

Public Sub ProcessLogFile(ByVal filePath As String)
‘ ガード節:ファイルの存在確認
If Not File.Exists(filePath) Then
Throw New FileNotFoundException(“指定されたファイルが存在しません。”, filePath)
End If

‘ Usingステートメントで確実なリソース解放(メモリリーク防止)を担保
Using reader As New StreamReader(filePath, System.Text.Encoding.UTF8)

Do
‘ 1行読み込み
Dim currentLine As String = reader.ReadLine()

‘ 【重要】EOF(ファイルの終端)に達したら即座に安全脱出
If currentLine Is Nothing Then Exit Do

‘ — ビジネスロジック(例:空行やコメント行のスキップ) —
If String.IsNullOrWhiteSpace(currentLine) OrElse currentLine.StartsWith(“#”) Then
Continue Do ‘ 次のループへスキップ
End If

‘ 実処理
ExecuteBusinessLogic(currentLine)

Loop ‘ 条件なしの無限ループに見えるが、内部の Exit Do で完全に制御されている

End Using
End Sub

Private Sub ExecuteBusinessLogic(ByVal line As String)
‘ 実際の業務処理
Console.WriteLine($”処理中: {line}”)
End Sub

End Class

このコードが優れている理由

1. Usingステートメントの活用: 例外が発生しようとも、`StreamReader` は確実に破棄(Dispose)される。リソースリークとは無縁だ。
2. 制御の局所化: 「無限 `Do…Loop` + 内部の `Exit Do`」の構造にすることで、ループの継続条件が複雑化した際にもスパゲッティコードになりにくい。
3. `Continue Do` の適切な利用: 処理対象外のデータをエレガントにスキップし、インデントの深化(Arrow Anti-pattern)を防いでいる。

5. 選択の基準まとめ(チーフアーキテクトからの提言)

どの構文を使うべきか迷ったときは、以下のマトリクスを思い出してほしい。

| 状況・要件 | 推奨する構文 | 理由 |
| :— | :— | :— |
| ループ内の処理を「絶対に1回は実行したい」 | `Do…Loop While` (後置) | 最初の1回を実行してから判定するため、初期化の手間がいらない。 |
| ループ開始前に条件を満たさない可能性がある | `While…End While` または `Do While…Loop` (前置) | 無駄な処理の実行を防ぐ。 |
| ファイル読み込みやDBのレコードフェッチ | `Do…Loop` + `Exit Do` | 終了条件が複雑になりがちなストリーム処理において、最も安全かつ明確に離脱できる。 |

最後に

コードの美しさは、そのまま保守性の高さに直結する。
「動けばいいや」で作られた場当たり的なループは、やがてシステム改修の際に開発者の足をすくい、深刻な障害を引き起こす。

今回伝授した「条件評価のタイミングの理解」と「安全な脱出制御」をマスターすれば、あなたの書くVB.NETコードは一段も二段も洗練された、プロフェッショナルな代物に生まれ変わるはずだ。

現場の信頼を勝ち取る堅牢なコードを、明日からの開発に役立ててほしい。

タイトルとURLをコピーしました