チェランの正解に加えて(そしてフレークの欠陥を示すために):
短絡評価(目前の問題に対するより良いリンク)
動作中の短絡評価:
VBScriptは(式を不必要に評価するために)熱心です:
オプション明示
Function F()
WScript.StdOut.Write "F() called ==> "
F = True
End Function
Dim A, R
For Each A In Array(False, True)
WScript.StdOut.Write CStr(A) & " and F() ==> "
If A And F() Then R = "YES" Else R = "NO"
WScript.StdOut.WriteLine R
WScript.StdOut.Write CStr(A) & " or F() ==> "
If A Or F() Then R = "YES" Else R = "NO"
WScript.StdOut.WriteLine R
Next
出力:
False and F() ==> F() called ==> NO
False or F() ==> F() called ==> YES
True and F() ==> F() called ==> YES
True or F() ==> F() called ==> YES
JScriptは怠惰です(不要なチェックはスキップされます):
function F() {
WScript.StdOut.Write("F() called ==> ");
return true;
}
var B = [false, true];
var R;
for (var I in B) {
var A = B[I];
WScript.StdOut.Write(A + " and F() ==> ");
if (A && F()) {R = "YES";} else {R = "NO";}
WScript.StdOut.WriteLine(R);
WScript.StdOut.Write(A + " or F() ==> ");
if (A || F()) {R = "YES";} else {R = "NO";}
WScript.StdOut.WriteLine(R);
}
出力:
false and F() ==> NO
false or F() ==> F() called ==> YES
true and F() ==> F() called ==> YES
true or F() ==> YES
Select Case False / Trueを使用すると、ネストされたIfを回避できます。
Option Explicit
Class C
Function F()
WScript.StdOut.Write "C.F() called ==> "
F = True
End Function
End Class
Class D
Public m_C
Private Sub Class_Initialize()
Set m_C = Nothing
End Sub
Function init()
Set init = Me
Set m_C = New C
End Function
End Class
Class I
Private m_I
Private Sub Class_Initialize()
m_I = 0
End Sub
Public Default Function Inc()
m_I = m_I + 1
Inc = Right(" " & m_I, 3) & " "
End Function
End Class
Dim N : Set N = New I
Dim O, R
For Each O In Array(Empty, "Nix", Nothing, New D, (New D).init())
WScript.StdOut.Write N() & TypeName(O) & " via nested Ifs ==> "
If IsObject(O) Then
If O Is Nothing Then
R = "O Is Nothing"
Else
If IsObject(O.m_C) Then
If O.m_C Is Nothing Then
R = "O.m_C Is Nothing"
Else
If O.m_C.F() Then
R = "YES"
Else
R = "NO"
End If
End If
Else
R = "O.m_C is not an object"
End If
End If
Else
R = "O is not an object"
End If
WScript.StdOut.WriteLine R
WScript.StdOut.Write N() & TypeName(O) & " via Select Case False ==> "
Select Case False
Case IsObject(O)
R = "O is not an object"
Case Not O Is Nothing
R = "O Is Nothing"
Case IsObject(O.m_C)
R = "O.m_C is not an object"
Case Not O.m_C Is Nothing
R = "O.m_C Is Nothing"
Case Else
If O.m_C.F() Then
R = "YES"
Else
R = "SURPRISE"
End If
End Select
WScript.StdOut.WriteLine R
WScript.StdOut.Write N() & TypeName(O) & " via SHORT Select Case False ==> "
Select Case True
Case Not IsObject(O), O Is Nothing, Not IsObject(O.m_C), O.m_C Is Nothing
R = "Something rotten"
Case Else
If O.m_C.F() Then
R = "YES"
Else
R = "SURPRISE"
End If
End Select
WScript.StdOut.WriteLine R
On Error Resume Next
If O Is Nothing Then R = "Surprise"
If Err.Number Then WScript.Echo N(), Err.Number, Err.Description
On Error GoTo 0
Next
出力:
1 Empty via nested Ifs ==> O is not an object
2 Empty via Select Case False ==> O is not an object
3 Empty via SHORT Select Case False ==> Something rotten
4 424 Object required
5 String via nested Ifs ==> O is not an object
6 String via Select Case False ==> O is not an object
7 String via SHORT Select Case False ==> Something rotten
8 424 Object required
9 Nothing via nested Ifs ==> O Is Nothing
10 Nothing via Select Case False ==> O Is Nothing
11 Nothing via SHORT Select Case False ==> Something rotten
12 D via nested Ifs ==> O.m_C Is Nothing
13 D via Select Case False ==> O.m_C Is Nothing
14 D via SHORT Select Case False ==> Something rotten
15 D via nested Ifs ==> C.F() called ==> YES
16 D via Select Case False ==> C.F() called ==> YES
17 D via SHORT Select Case False ==> C.F() called ==> YES
出力4と8を無視して、トリプル1〜3、... 15〜17だけを比較し、対応するコード行を見ると、次のようになります。
- ネストされたIfとSelectCaseは、結果と同等です
- 詳細に興味がない場合は、コンマで区切られた式のリストが短絡されているため、SHORT Select Caseはすべての「不良ケース」を1行でフィルタリングできます(ただし、順序は重要です!)。
- 詳細が必要な場合は、SelectCaseの方が読みやすく編集/拡張しやすいです
フレークの答えの欠陥:
出力行4および8は、IsNothingテストが非オブジェクトに適用された場合に失敗することを示しています。したがって、IsObject()チェックで保護する必要があります。次に、チェックを組み合わせるという問題が発生します(これはその貢献では完全に無視されます)。