.NET VB 制御構造
.NET VB(VisualBasic)の条件分岐や同じ処理を繰り返し実行する制御構造(If、Select、For~Next、For Eath、Continue For、While End While、Do While、Goto)について解説風に記録しておく。
- 制御構造とは
- 条件分岐
- 繰り返し
- For Next:決められた回数の処理を繰り返す
- For Each Next:コレクション内のすべてのオブジェクトに同じ処理を実行
- Exit For:For文から強制的に抜ける
- Continue For:For Next処理中に先頭に強制的に戻す。
- While End While:条件が成立中は同じ処理を繰返す
- While:無限ループ
- Exit While:Whileを強制的に抜ける
- Do While~Loop:条件式がTrueの間処理を繰り返す
- Do ~Loop While:条件式がTrueの間処理を繰り返す
- Do Untile Loop:条件式がTrueの間処理を繰り返す
- Exit Do:Do Loopから強制的に抜ける
- 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文が巻物のようになると、メンテナンスする場合に処理の内容が把握しづらくなり、ミスを誘発する。コーディングした者がシステムの寿命を迎えるまで、メンテナンスし続けることはかなり稀である。大抵は途中で、転職や異動等で他者に担当が変わる。また、月日が進むことにより開発者自身の記憶もあいまいになり、ソースコードを追っかけることになる。
システムリリース後や運用フェーズで、最適化する方法もあるがあまりやりたがらない、一度、正常に動いているものに手を入れるということは、コストもかかる、何より問題があった場合に顧客との契約上のトラブルが発生する。そのため、大抵は後の祭り状態となりメンテナンス時に苦労することになる。
開発時にしっかりとコードレビューで防止することが望ましい。