.NET VB 制御構造

最終更新日

.NET VB(VisualBasic)の条件分岐や同じ処理を繰り返し実行する制御構造(If、Select、For~Next、For Eath、Continue For、While End While、Do While、Goto)について解説風に記録しておく。

制御構造とは

制御構造は、指定条件によって処理を変えたり、指定条件が満たされているもしくは、満たされなくなった場合、特定の処理を繰り返し実行したりすることができる。

条件分岐

if~then:条件分岐により処理を分ける

処理を特定の条件で分けたいとき、if~thenを使用する。制御文の中では一番使用される。

書式1

if 条件式 then 条件が満たされた場合の処理 

書式2

if 条件式 then
End if

書式3

if 条件式 then
 条件式が満たされた場合の処理を書く
else
 条件式が満たされなかった場合の処理を書く
end if

サンプル:書式1

Dim classcode1 As String = "01"  '分類1コード 書籍
If classcode1 = "01" Then Console.WriteLine("分類は、書籍です。")

サンプル:書式2

Dim classcode1 As String = "01"  '分類1コード 書籍
If classcode1 = "01" Then 
    Console.WriteLine("分類は、書籍です。")
End if

サンプル:書式3

Dim classcode1 As String = "01"  '分類1コード 書籍
If classcode1 = "01" Then 
    Console.WriteLine("分類は、書籍です。")
Else
    Console.WriteLine("分類は、マッチしません。")
End if

if~then:3つ以上の条件分岐により処理を分ける

3つ以上の条件で処理を分岐させたい場合は、Elseの次にIf 条件式 Thenを繋げていく。また、select caseと同じように処理を分けることができます。

構文

if 条件式1 then
   条件式1が満たされた場合の処理を書く
else if 条件式2 then
  条件式2が満たされた場合の処理を書く
else if 条件式3 then
  条件式3が満たされた場合の処理を書く
else
  どの条件式にも合致しなかった場合の処理を書く
end if

サンプル

Dim classcode1 As String = "01"  '分類1コード 書籍
If classcode1 = "01" Then 
    Console.WriteLine("分類は、書籍です。")
Else If classcode1 = "02" Then 
    Console.WriteLine("分類は、文具です。")
Else If classcode1 = "03" Then 
    Console.WriteLine("分類は、健康器具です。")
Else
    Console.WriteLine("分類は、マッチしません。")
End if

if~then:入れ子(ネスト)

if thenやelseのブロックにさらにifを入れることができる。これは、入れ子(ネスト)と言います。

構文

if 条件式1 then
   条件式1が満たされた場合の処理を書く
   if 条件式2 then
     条件式2が満たされた場合の処理を書く
   else
     条件式2が満たされなかった場合の処理を書く
   end if
end if

サンプル

Dim classcode1 As String = "01"  '分類1コード 書籍
Dim classcode2 As String = "02"  '分類2コード ビジネス書
If classcode1 = "01" Then
    If classcode2 = "02" Then
        Console.WriteLine("分類は、ビジネス書です。")
    ElseIf classcode2 = "03" Then
        Console.WriteLine("分類は、漫画です。")
    End If
End If

Selete Case:条件式の結果に応じて処理を分岐する

1つの式の複数の結果に対して、それぞれ処理を分岐させることができる。caseの後に一致する式を記載するまた、caseは複数書くことができる。 Case Elseは条件がマッチしなかった場合の処理であるが、省略することもできる。

構文

Select Case 条件式
   Case 式1
       条件合致した場合の処理を書く(ブロック1)
   Case 式2
       条件合致した場合の処理を書く(ブロック2)
   ・
  ・
   Case Else '省略可能である。
End Select

サンプル

Dim classcode As String = "01"  '分類コード
    Select Case classcode
        Case "01"
            Console.WriteLine("分類コード01は、書籍です。")
        Case "02"
            Console.WriteLine("分類コード02は、文具です。")
        Case Else
            Console.WriteLine("分類コードは、分類不能です。")
End Select

繰り返し

指定された回数繰り返すFor~Nextステートメントと、条件により処理を繰り返すWhile~ステートメントについて解説。

For Next:決められた回数の処理を繰り返す

Toで指定した回数分処理を繰り返します。また、Stepでカウント数を変更をすることができる。step 1 あれば1.2.3とカウントしていく。step 2であればカウントは2.4.6とカウントしていく。

書式1:カウンター変数を事前定義

dim i As Integer                         'カウンター変数をForブロック外で定義
For カウンター変数 = 初期値 To 終了値 Step カウンターの増加値
    繰り返すして実行する処理
Next 変数 '変数は省略可能

書式2:For内でカウンター変数を定義

For カウンター変数 As データ型 = 初期値 To 終了値 Step カウンターの増加値
    繰り返すして実行する処理
Next 変数

書式3:Step省略パターン

For カウンター変数 As データ型 = 初期値 To 終了値
    繰り返すして実行する処理
Next 変数

stepを省略した場合は、step は1.2.3とカウントする。

サンプル:カウンター変数を事前定義

dim i As Integer
dim count As Integer = 0

For i = 0 to 5
    count = count + 1
    Console.WriteLine("現在のカウント:" & count.ToString())
Next i

Console.WriteLine("ブロック外 カウンター変数 i:" & i.ToString()) 'ブロック外でもカウンター変数にアクセスできる。

サンプル:For内でカウンター変数を定義

Dim count As Integer = 0

For i As Integer = 0 To 5 Step 2
    count = count + 1
    Console.WriteLine("現在のカウント:" & count.ToString())
Next i

ブロック外では、カウンター変数にアクセスできない。

サンプル:Step省略パターン

Dim count As Integer = 0
For i As Integer = 0 To 5
    count = count + 1
    Console.WriteLine("現在のカウント:" & count.ToString())
Next i

カウンター変数名の定義
カウンター変数の名前は、「i」を使用します。複数のカウンター変数を使用する場合は、i、j、k・・・とアルファベット順に使用する。

ブロック変数
書式2で定義したカウンター変数は、Forのブロック内でしか使用できない。
ただし、書式1でカウンター変数をブロック外で定義した場合は、ブロック外でも変数を使用することができる。

For Next:入れ子(ネスト)

For Nextのループ内にループを入れることができます。二重ループと呼び、別名として入れ子、ネストという言い方をする。また、ネスト数は3重、4重…と多重にすることができる。用途としては、データベースからレコードを取得して、画面に一覧として表示する時等に使われる。

書式

For カウンター変数1 As データ型 = 初期値 To 終了値

     For カウンター変数2 As データ型 = 初期値 To 終了値
           繰り返すして実行する処理
     Next 変数2

Next 変数1

サンプル

For i As Integer = 0 To 5
    For j As Integer = 0 To 5
        Console.WriteLine("i行:" & i.ToString() & ",j列:" & j.ToString())
    Next j
Next i

For Each Next:コレクション内のすべてのオブジェクトに同じ処理を実行

オブジェクトなどの関連要素の集合体であるコレクションまたは、配列を先頭要素から終末要素までを1つずつ取り出し、繰り返し処理をする場合は、「For Each Next(フォー・イーチ・ネクスト)ステートメント」を利用します。これもデータベースからレコードを取得し、1レコードずつ処理して画面に表示するなどの利用が多い。

構文

For Each オブジェクトを格納する変数 In コレクションまたは配列
    繰り返すして実行する処理
Next 

サンプル

For Each row As DataRow In ds.Tables("DatTable").Rows
     Console.WriteLine("商品マスタ価格:" & row("PRICE").ToString())
 Next

Exit For:For文から強制的に抜ける

For Nextの繰り返し途中で、強制的に抜けるにはExit Forを使用する。

サンプル

For i As Integer = 0 To 5
    Console.WriteLine("現在のカウント:" & i.ToString())
    If i = 2 Then
        Exit For
    End If
Next i

Continue For:For Next処理中に先頭に強制的に戻す。

For Nextの繰り返し途中で、強制的に処理を先頭に戻して次の処理から始めるためには、Continue Forステートメントを使用する。

サンプル

For i As Integer = 0 To 5
    If i = 2 Then
        Continue For   'カウンターが2の時、Forの先頭に戻しコンソール出力処理をスキップする
    End If
    Console.WriteLine("現在のカウント:" & i.ToString())
Next i

出力結果は、0~5まで出力されるが2はContinueで戻されているため出力されない。

While End While:条件が成立中は同じ処理を繰返す

While End Whileは条件式が真(True)の場合、処理を繰り返します。(ループが続く)。For Nextは、ループ回数が決まっているもしくは、計算できる場合は使用できるが、ループ回数が条件によって変わる場合は、While End Whileステートメントを使用する。

構文

While 条件式
  繰り返す処理
End While

サンプル

Dim cReader As New System.IO.StreamReader("C:\temp\サンプル.txt", System.Text.Encoding.Default)

Try
   ' 読み込みできる文字がなくなるまで繰り返す
   While (cReader.Peek() >= 0)

   ' ファイルを 1 行ずつ読み込む
   Dim stBuffer As String = cReader.ReadLine()
   Console.WriteLine(stBuffer)

   End While

Catch ex As Exception
Finally
   cReader.Close()
End Try

While:無限ループ

whileの条件式にTrueを指定すると、処理が無限に繰り返します。また、条件が常に真(True)となる条件を指定しても無限ループになります。

サンプル:Trueを指定した場合

'whileにTrueを指定した場合
While True
   Console.WriteLine("無限ループ処理中")

End While

サンプル:常にTrueになる条件を指定した場合

'条件式が常に真(True)になるようにしたケース

Dim count As Integer = 0

While count < 1
     Console.WriteLine("無限ループ処理中")
End While

Exit While:Whileを強制的に抜ける

Whileブロックから強制的に抜ける(終了)ためには、Exit Whileを実行する。

構文

Do While 条件式
  処理
    if 条件 then
       Exit While    'ifの条件が満たされたらWhileループを抜ける。
    End if
Loop

サンプル

Dim count As Integer = 1
'カウンターが10になったら、Whileを終了させる。
While True
    Console.WriteLine("カウンター:" & count.ToString())
    If count = 10 Then
        Exit While
    End If

    count += 1
End While

Do While~Loop:条件式がTrueの間処理を繰り返す

条件式が真(True)の間だけ処理を繰り返す。

構文

Do While 条件式
  処理
Loop

サンプル

Dim count As Integer = 1
Do While count < 10

    Console.WriteLine("カウンター:" & count.ToString())

    count += 1

Loop

Do ~Loop While:条件式がTrueの間処理を繰り返す

条件式が真(True)の間だけ処理を繰り返す。Do While~Loopと異なる点は、処理をしてからループ判定をすることである。

構文

Do
  処理
Loop While 条件式

サンプル

Do
    count += 1
    Console.WriteLine("カウンター:" & count.ToString())
Loop While count < 10

Do Untile Loop:条件式がTrueの間処理を繰り返す

Do While Loopステートメントでは、条件が偽(False)である限り同じ処理が繰り返され、条件が真(True)になったところで繰り返し処理が終わります。

構文

Do Until 条件式
  処理
Loop

サンプル

Dim count As Integer = 1
Do Until count > 10
    Console.WriteLine("カウンター:" & count.ToString())
    count += 1
Loop

Exit Do:Do Loopから強制的に抜ける

Do Loopから強制的に抜けるには、Exit Doを使用する。

サンプル

Do While count < 10
     count += 1
     Console.WriteLine("カウンター:" & count.ToString())
     If count = 5 Then
         Exit Do
     End If
Loop

Goto:指定したラベルまで一気に処理を飛ばす。

特定の処理の位置から、指定したラベルの位置まで処理が一気にジャンプしたい場合は、Gotoを使用する。多重ループから一気に処理を抜ける場合は便利である。多用は注意が必要である、処理の可読性がかなり悪くなる。

構文

GoTo ラベル
    処理・・・
ラベル:

サンプル

Dim count As Integer = 0
Do While count < 10
    count += 1
    Console.WriteLine("カウンター:" & count.ToString())
    If count = 5 Then
        GoTo procexit      'procexit:ラベルにジャンプする。
    End If
Loop

procexit:                   'ジャンプ先
        Console.WriteLine("プログラム終了")

ネスト(入れ子)問題

if、For、While、Select Caseを含む ネストは、2重から3重程度にしておく。これは、ソースコードの可読性が悪くなり処理が把握しづらくなる。

4重、5重以上となる場合は、関数化するかメソッドとして切り出すようにするとよい。

所感:いまだに現場では・・・
さて、どの言語、どのプロジェクトや現場でもそうだが、今だに4重以上のネストしているシステムが多い。ネストは、ifやfor等を含めても2重か3重程度にしておくほうがよい。ネストとselect case文が巻物のようになると、メンテナンスする場合に処理の内容が把握しづらくなり、ミスを誘発する。コーディングした者がシステムの寿命を迎えるまで、メンテナンスし続けることはかなり稀である。大抵は途中で、転職や異動等で他者に担当が変わる。また、月日が進むことにより開発者自身の記憶もあいまいになり、ソースコードを追っかけることになる。
システムリリース後や運用フェーズで、最適化する方法もあるがあまりやりたがらない、一度、正常に動いているものに手を入れるということは、コストもかかる、何より問題があった場合に顧客との契約上のトラブルが発生する。そのため、大抵は後の祭り状態となりメンテナンス時に苦労することになる。
開発時にしっかりとコードレビューで防止することが望ましい。