IIf() と If のパフォーマンスの違い
-
09-06-2019 - |
質問
Visual Basic で、 IIf
の代わりに関数 If
声明?
解決
VBには以下のようなものがあります If
質問が言及しているステートメントは、次のように思います。
' Usage 1
Dim result = If(a > 5, "World", "Hello")
' Usage 2
Dim foo = If(result, "Alternative")
1 つ目は基本的に C# の 3 項条件演算子で、2 つ目はその合体演算子 (return result
そうでなければ Nothing
, 、その場合は戻ります "Alternative"
). If
したがって置き換えられました IIf
そして後者は時代遅れです。
C# と同様、VB の条件式 If
演算子がショートサーキットするため、次のように安全に記述できるようになりました。これは、 IIf
関数:
Dim len = If(text Is Nothing, 0, text.Length)
他のヒント
IIf()
true と false の両方のコードを実行します。数値の代入などの単純な処理の場合、これは大した問題ではありません。しかし、何らかの処理を必要とするコードの場合、一致しない条件を実行することでサイクルが無駄になり、副作用が発生する可能性があります。
コードの図:
Module Module1
Sub Main()
Dim test As Boolean = False
Dim result As String = IIf(test, Foo(), Bar())
End Sub
Public Function Foo() As String
Console.WriteLine("Foo!")
Return "Foo"
End Function
Public Function Bar() As String
Console.WriteLine("Bar!")
Return "Bar"
End Function
End Module
出力:
Foo!
Bar!
また、IIf に関するもう 1 つの大きな問題は、引数 [1] にある関数を実際に呼び出すことです。したがって、次のような状況がある場合:
string results = IIf(Not oraData.IsDBNull(ndx), oraData.GetString(ndx), string.Empty)
実際には例外がスローされますが、ほとんどの人がこの関数を初めて見たときは、このように動作するとは考えられません。これにより、アプリケーション内で修正が非常に困難なバグが発生する可能性もあります。
[1]IIf関数 - http://msdn.microsoft.com/en-us/library/27ydhh0d(VS.71).aspx
型推論メカニズムを正しく使用するには、IIf の代わりに If を使用することをお勧めします (Option Infer On)
この例では、 If を使用すると、キーワードが文字列として認識されます。
Dim Keywords = If(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
それ以外の場合は、 Object として認識されます。
Dim Keywords = IIf(String.IsNullOrEmpty(SelectedKeywords), "N/A", SelectedKeywords)
によると この男, IIf には、If/Then の最大 6 倍の時間がかかる場合があります。YMMV。
さらに、この場合、パフォーマンスよりも読みやすさの方が優先されるはずです。たとえ IIF の方が効率的だったとしても、対象ユーザーにとっては明らかに読みにくくなります (Visual Basic で作業している場合は、他のプログラマが自分のコードを簡単に読めるようにしたいと思うでしょう。これが VB の最大の利点です...私の意見では、IIF のような概念では失われます)。
また、 「IIF は関数ですが、IF は言語構文の一部です」...これは、確かに、If の方が速いだろうということを意味します...if 関数内のロジックを実行するためにメモリ内の別の領域に移動する必要がなく、If ステートメントを直接小さなオペコードのセットに要約できるためです。おそらくそれはありきたりな違いですが、注目に値します。
If と IIf の主な違いは次のとおりだと思います。
if(test [boolean]、statement1、statement2)は、テスト値に従ってsatement1またはstatement2が実行されることを意味します(1つのステートメントが実行されます)
dim obj = iif(test [boolean]、statement1、statement2)両方のステートメントが実行されることを意味しますが、テスト値に従って、そのうちの1つは(obj)に値を返します。
したがって、ステートメントの 1 つが例外をスローする場合、とにかく (IIf) で例外をスローしますが、(If) では、条件が値を返す場合に備えて例外をスローします。
...なぜ 6 倍もの時間がかかるのかについては、Wiki を引用してください。
IIFはライブラリ関数であるため、常に関数呼び出しのオーバーヘッドが必要になりますが、条件付き演算子はインラインコードを生成する可能性が高くなります。
基本的に IIf は C++/C# の三項演算子に相当するため、必要に応じて 1 行の if/else 型ステートメントを作成できます。必要に応じて、評価する関数を与えることもできます。
それらの機能は異なります!おそらく、IF ステートメントを使用するだけで済みます。IIF は両方の機能に加えて標準の IF ステートメントも実行するため、常に遅くなります。
なぜ IIF 関数があるのか疑問に思っているなら、おそらくこれが説明になるでしょう。
Sub main()
counter = 0
bln = True
s = iif(bln, f1, f2)
End Sub
Function f1 As String
counter = counter + 1
Return "YES"
End Function
Function f2 As String
counter = counter + 1
Return "NO"
End Function
したがって、この後カウンタは 2 になりますが、s は「YES」のみになります。このカウンターのようなものは役に立たないことはわかっていますが、IF が true か false かは関係なく、両方を実行する必要がある関数があり、一方の値を変数に代入するだけです。