除了 Cheran 的正确答案(并显示 Flakes 中的缺陷):
短路评估(手头问题的更好链接)
实际短路评估:
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 并查看对应的代码行,您会看到
- 嵌套的 Ifs 和 Select Case 在结果上是等价的
- 如果您对细节不感兴趣,SHORT Select Case 可以在一行中过滤所有“坏情况”(尽管顺序很重要!),因为逗号分隔的表达式列表是短路的
- 如果您需要详细信息,选择案例更易于阅读/编辑/扩充
Flakes 回答中的缺陷:
输出第 4 行和第 8 行显示,如果应用于非对象,Is Nothing 测试将失败。所以必须用 IsObject() 检查来保护它。然后会出现组合检查的问题(在该贡献中完全忽略了该问题)。