■ 条件分岐について
今回は、条件分岐について詳しく解説したいと思います。
よく聞かれる質問に、「If文とSelect文、どっちを使ったらいいかよくわかりません」といったものがあります。
これに対して、「ケースバイケースですよ」と答えるのは正答ですが、決して良回答ではありません。
どういったケースに、どちらの条件式を使うのかをきちんと教えてあげなければ、その人のプログラミングスキルはいつまでたっても上達しないでしょう。
If文について
書式:
If 条件式 Then
真の場合
Else
偽の場合
End If
If文の一般的な使い方は、ある条件に対して真か偽かを判定するのに使用します。この辺りをよく理解していない方が結構います。
例えば、
Dim MyLng As Long
If MyLng = 0 Then
Debug.Print "MyLngは0です"
Else
Debug.Print "MyLngは0ではありません"
End If
これはOKです。でも、
Dim MyFlg As Boorean
If MyFlg = True Then
Debug.Print "MyFlgは真です"
Else
Debug.Print "MyFlgは偽です"
End If
この書き方はおかしいです。なぜそうなるのでしょう?
If文は条件式が真か偽で判断します。最初の「MyLng = 0」はこの式が真か偽かを判定しています。
MyLngに0が代入されていれば当然条件式は真になり、0以外が代入されていれば偽になります。
しかし、次の例の「MyFlg = True」は、ブール型のMyFlgがすでに真・偽どちらかの値を持っているのに、再度条件式で判定させています。つまり、無駄な処理を行わせているのです。
If MyFlg = True Then は If MyFlg Then と書けば済む話です。
(偽の場合を判定させたいときは、If Not MyFlg Then と記述します)
ElseIfについて
よく、Select文の代わりにElseIfを用いて書き換えをしている解説を目にしますが、Select文とElseIfを用いた条件判定は意味が異なりますので注意してください。
Select文が、評価対象に対して条件式を並列化したものであるのに対して、ElseIfはあくまでIf文のネスト構造を並列化したものです。
例えば、
If 条件式1 Then
条件式1が真の場合
ElseIf 条件式2 Then
条件式1が偽で、条件式2が真の場合
ElseIf 条件式3 Then
条件式1,2が偽で,条件式3が真の場合
End If
これと、
If 条件式1 Then
条件式1が真の場合
Else
If 条件式2 Then
条件式1が偽で、条件式2が真の場合
Else
If 条件式3 Then
条件式1,2が偽で,条件式3が真の場合
End If
End If
End If
この文は同じ意味です。
ちなみに、論理演算子のAndを用いたIf文は、ネスト構造に分解できます。
例:
If 条件式1 And 条件式2 Then
条件式1,2が真だった場合
End If
これは、
If 条件式1 Then
If 条件式2 Then
条件式1,2が真だった場合
End If
End If
この文と同じ意味になります。ただし、上の書き方は条件式1と条件式2の両方を評価するのに対して、下の書き方は条件式1が真だった場合のみ、条件式2を評価するため、わずかですが処理が軽減できます。
論理演算子を複数使った条件判定には必ずカッコを使用してください。開発者の意図しなかった誤動作を防ぐことができます。
例:
If (条件式1 Or 条件式2) And 条件式3 Then
と、
If 条件式1 Or 条件式2 And 条件式3 Then
は、異なった動作をします。
理由は、AndとOrの論理演算子を混合させて使用した場合、And演算子の結合力のほうが強く働くためです。
上記の例で条件式1が真で、条件式3が偽の場合、(条件式2は真偽どちらでも構いません)
上のケースは条件式3が偽のため、全体の条件判定は偽になります。
(条件式1が真または条件式2が真で、かつ条件式3が真、の場合に真)
下のケースはどうなるでしょう?
条件式1が真なので、全体の条件判定は真になります。これはAnd演算子のほうが強い結合力を持つため、条件式1 Or (条件式2 And 条件式3)このように評価してしまうからです。
(条件式1が真または、条件式2が真でかつ条件式3が真、の場合に真)
このように、カッコの有無で条件判定が異なってきます。
ただし、いくらカッコをつけるからといっても、あまりにも複雑な条件判定を、論理演算子を多用して一つにまとめるのはお勧めしません。
開発者本人にも、条件判定の論理構造が読み取れなくなってしまいます。
素直に、If文をネストするか、ロジックそのものを見直したほうがよいでしょう。
Select文について
よく、Select文は単一のオブジェクトに対して複数の評価を行うときに使用し、評価の対象が複数のときはSelect文では判定できません。…といった主旨の解説を見受けますが、そんなことはありません。
Select文でも、複数のオブジェクトに対して判定を行うことが可能です。
例:
Select Case 評価対象
Case 条件1
条件1が真の場合
Case 条件2
条件2が真の場合
Case 条件3
条件3が真の場合
Case Else
条件1〜3が偽の場合
End Select
これが、一般的なSelect文の使用法です。CやJAVAのswitch文と異なり、breakは必要ありません。上から順に評価していき、真のケースがあった場合、その処理を行い、Select文を抜けます。ですので逆にbreakを記述しないで、途中まで評価させるといった使用法はできないので注意が必要です。
またSelect文はElseIfと異なり、条件の評価を一回しか行いません。評価対象が単一の場合、ElseIfで複数回評価させるよりも、Select文で一回だけ評価したほうが、若干実行速度は速くなります。
評価対象が複数ある場合は、このように記述します。
例:
Select Case True
Case 条件式1 And 条件式2
条件式1が真でかつ条件式2が真の場合
Case 条件式1
条件式1が真の場合
Case 条件式2
条件式2が真の場合
Case Else
条件式1,2が偽の場合
End Select
この場合、Case節に条件式を記述します。これは、
If 条件式1 And 条件式2 Then
条件式1が真でかつ条件式2が真の場合
Else
If 条件式1 Then
条件式1が真の場合
ElseIf 条件式2 Then
条件式2が真の場合
Else
条件式1,2が偽の場合
End If
End If
この記述と同じ意味になります。ただし、どちらが可読性がよいかは疑問です。評価対象が複数ある場合は、素直にIf文を用いたほうが、後々メンテナンスしやすいでしょう。
ちなみに一般的なSelect文のCase節の書き方は次のようになります。
値が1,2,3いずれかの場合 |
Case 1, 2, 3 |
値が1〜3の範囲 |
Case 1 To 3 |
値が1,2または3〜5の範囲 |
Case 1, 2, 3 To 5 |
値が5以上 |
Case Is >= 5 |
IIf関数について
書式:
IIf(条件式,真の返り値,偽の返り値)
条件式に対して真の場合第2引数を、偽の場合第3引数を値として返します。ワークシート関数のIf関数と同じ文法です。
このIIf関数に限っていえば、あまり使用することをお勧めしません。その理由は、条件式の真偽にかかわらず必ず真の返り値、偽の返り値の両方の式を評価するからです。つまり余分な処理を行っている分、VBAの実行速度が低下します。
さらに必ず両方の式を評価するということは、次のようなケースには使用できません。
MyLng = IIf(MyLng <> 0, 2 / MyLng, CstMyLng)
この場合、MyLngが0だと0除算エラーが発生します。これは、条件式 MyLng <> 0 が真か偽かにかかわらず、2 / MyLng の式を評価しているためです。
一般的なIf文ならこのようなエラーは発生しません。
If MyLng <> 0 Then
MyLng = 2 / MyLng
Else
MyLng = CstMyLng
End If
以上、条件分岐についてみてきました。条件分岐式の書き方は可読性のみならず、論理構造そのものを変化させます。
プログラミングの上手い下手がここであらわれるといっても過言ではありません。
コードがスパゲッティになる人の条件分岐式は、必ずといっていいほど適切な記述をされていません。
トリッキーなコードを書くのではなく、メンテナンスしやすく他の人にわかりやすいコードを書くほうが、ずっと価値のあることです。
|