#38 | Select CaseステートメントとChoose関数の比較 | ||||||||||
#37ではIf〜ElseステートメントとIIf関数について比較してみましたが、これとまったく同様の関係を持っているのがSelect CaseステートメントとChoose関数です。Select Caseステートメントでは、Selectの次に記述された変数などの値に応じて、それぞれのCase節のコードを実行します。そこには複数行のコードを書くこともできます。一方、Choose関数は、IIf関数に似て、最初の引数の値によって2番目以降の対応する引数を返すものです。 RetValue = Choose(Index, Choice1, Choice2, ...., Choice-n) 複数行の処理を実行させることはできませんし、条件となる値(Index)も1・2・3・・・・・というように、1から始まる連続した整数である必要がありますが、分岐処理内容によっては、Select Caseステートメントより非常にシンプルに処理を表現することができます。 これら2つの違いも基本的にはIf〜Elseステートメント/IIf関数と同じと考えられますが、ここではそれをテストコードで実際に確認してみたいと思います。 まずはじめに、次のようなテスト用コードを使って、Choose関数の内部動作を確認してみましょう。イミディエイトウィンドウからcasetest_1プロシージャを実行してみます。 Sub casetest_1() 'Choose関数の動作の仕組みの検証 Dim a a = 1 Select Case a Case 1 dummy "Select Case その1" Case 2 dummy "Select Case その2" Case 3 dummy "Select Case その3" End Select a = Choose(a, dummy("Choose その1"), dummy("Choose その2"), dummy("Choose その3")) End Sub Function dummy(strText As String) Debug.Print strText End Function 実行結果 IIf関数と同様、Choose関数でも、「a = 1」であるにも関わらず、2番目以降の引数に指定されたプロシージャがすべて呼び出されていることが確認できます。 次に、ループによってSelect CaseステートメントとChoose関数を多数回実行し、その時間を比べてみることにします。 ここでは次のような2つのコードを用意しました。1つ目は単に変数に値を代入するもの、2つ目は関数呼び出しを含めて、少々複雑な演算を実行させています。 Sub casetest_2() '単に値を代入する場合のSelect CaseとChooseの比較 Dim ilngLoop As Long Dim lngTmp As Long Dim lngRet As Long ts_Watch "処理開始", True For ilngLoop = 1 To 9999999 lngTmp = (ilngLoop Mod 5) + 1 Select Case lngTmp Case 1 lngRet = 11 Case 2 lngRet = 22 Case 3 lngRet = 33 Case 4 lngRet = 44 Case 5 lngRet = 55 End Select Next ilngLoop ts_Watch "Select Case ステートメント" For ilngLoop = 1 To 9999999 lngTmp = (ilngLoop Mod 5) + 1 lngRet = Choose(lngTmp, 11, 22, 33, 44, 55) Next ilngLoop ts_Watch "Choose関数" End Sub Sub casetest_3() '関数を呼び出す場合のSelect CaseとChooseの比較 Dim ilngLoop As Long Dim lngTmp As Long Dim dblRet As Double ts_Watch "処理開始", True For ilngLoop = 1 To 9999999 lngTmp = (ilngLoop Mod 5) + 1 Select Case lngTmp Case 1 dblRet = Sin(ilngLoop) / 2 Case 2 dblRet = Sin(ilngLoop) / 3 Case 3 dblRet = Sin(ilngLoop) / 4 Case 4 dblRet = Cos(ilngLoop) Case 5 dblRet = Tan(ilngLoop) End Select Next ilngLoop ts_Watch "Select Case ステートメント" For ilngLoop = 1 To 9999999 lngTmp = (ilngLoop Mod 5) + 1 dblRet = Choose(lngTmp, _ Sin(ilngLoop) / 2, _ Sin(ilngLoop) / 3, _ Sin(ilngLoop) / 4, _ Cos(ilngLoop), _ Tan(ilngLoop)) Next ilngLoop ts_Watch "Choose関数" End Sub それぞれの実行結果は次のとおりです。 ご覧のように、やはりIIf関数と同様に、Choose関数はSelect Caseステートメントに比べてパフォーマンスが劣ることが分かります。特に、1つ目のコードでは、単に固定的な値を代入しているだけなのですが、IIf関数に比べて絶対量がかなり増えています。Choose関数の場合、ふつうはIIf関数と違って何個もの引数を指定することが多いと思いますが、その分の違いが大きく現れているのかもしれません。そして、2つ目のコードでは、約1千万回の処理をしているとはいえ、38秒という非常に大きな時間を要しています。2番目から6番目の引数のすべての演算式が実行されることから考えれば、Select Caseステートメントの少なくても5倍のコストがかかって当然ですが、それでも絶対値としてかなり大きな時間です。これらのことから、やはりChoose関数に関しても「繰り返し処理では多用しない方がよい」、「引数に関数やプロシージャが含まれるときはSelect Caseステートメントにした方がよい」ということがいえるでしょう。とはいえ、もちろん1回当たりの処理時間はμ秒のレベルなので、少ない回数であれば影響はないといってよいでしょう。 |
|||||||||||
|
Copyright © T'sWare All rights reserved |