VBA Short-Circuit `And` Alternatives [duplizieren]
Diese Frage hat hier bereits eine Antwort:
AndAlso / OrElse in VBA 7 answersVBA schließt @ nicht ku
VBA unterstützt kein Kurzschließen - anscheinend, weil es nur bitweise And / Or / Not usw.-Operationen hat. Von demVBA Sprachspezifikation: "Logische Operatoren sind einfache Datenoperatoren, die bitweise Berechnungen für ihre Operanden durchführen." In diesem Licht ist es sinnvoll, dass VBA mit @ entworfen wurtrue = &H1111
undfalse = &H0000
: Auf diese Weise können logische Anweisungen als bitweise Operationen ausgewertet werden.
as Fehlen eines Kurzschlusses kann zu Problemen führe
Performance: dasReallyExpensiveFunction()
wird immer ausgeführt, wenn diese Anweisung ausgewertet wird, auch wenn dies aufgrund des Ergebnisses der linken Seite der Bedingung nicht erforderlich ist.
If IsNecessary() And ReallyExpensiveFunction() Then '... End If
Errors: Wenn MyObj Nothing ist, führt diese bedingte Anweisung zu einem Laufzeitfehler, da VBA weiterhin versucht, den Wert von @ zu überprüfeProperty
If Not MyObj Is Nothing And MyObj.Property = 5 Then '... End If
Die Lösung, mit der ich das Kurzschlussverhalten implementiert habe, ist verschachteltIf
s
If cond1 And cond2 Then
'...
End If
Wir
If cond1 Then
If cond2 Then
'...
End If
End If
Auf diese Weise geben die If-Anweisungen das kurzschlussartige Verhalten an, sich nicht die Mühe zu machen, @ auszuwertecond2
obcond1
istFalse
.
Wenn es eine Else-Klausel gibt, werden doppelte Codeblöcke erstellt
If Not MyObj Is Nothing And MyObj.Property = 5 Then
MsgBox "YAY"
Else
MsgBox "BOO"
End If
Wir
If Not MyObj Is Nothing Then
If MyObj.Property = 5 Then
MsgBox "YAY"
Else
MsgBox "BOO" 'Duplicate
End If
Else
MsgBox "BOO" 'Duplicate
End If
Gibt es eine Möglichkeit, @ neu zu schreibIf
-Anweisungen, um das Kurzschlussverhalten beizubehalten, aber doppelten Code zu vermeiden?
Vielleicht mit einer anderen Verzweigungsanweisung wieSelect Case
?
Um der Frage einen Kontext hinzuzufügen, ist hier der spezielle Fall, den ich betrachte. Ich implementiere eine Hash-Tabelle, die Kollisionen behandelt, indem sie in einer verknüpften Liste verkettet werden. Die zugrunde liegende Array-Größe wird als Zweierpotenz erzwungen, und die Hashes werden auf die aktuelle Array-Größe verteilt, indem sie auf die entsprechende Länge gekürzt werden.
Angenommen, die Array-Länge beträgt 16 (binär 10000). Wenn ich einen Schlüssel habe, der mit 27 (binär 11011) hascht, kann ich ihn in meinem 16-Slot-Array speichern, indem ich nur die Bits innerhalb der Grenze dieser Array-Größe halte. Der Index, in dem dieser Artikel gespeichert werden würde, ist(hash value) And (length of array - 1)
was in diesem Fall @ i(binary 11011) And (1111)
welches ist1011
Das ist 11. Der tatsächliche Hash-Code wird zusammen mit dem Schlüssel im Slot gespeichert.
Beim Nachschlagen eines Elements in der Hash-Tabelle in einer Kette müssen sowohl der Hash als auch der Schlüssel überprüft werden, um festzustellen, ob das richtige Element gefunden wurde. Wenn der Hash jedoch nicht übereinstimmt, gibt es keinen Grund, den Schlüssel zu überprüfen. Ich hatte gehofft, durch Verschachtelung der Ifs eine geringfügige immaterielle Leistung zu erzielen, um das Kurzschlussverhalten zu ermitteln:
While Not e Is Nothing
If keyhash = e.hash Then
If Key = e.Key Then
e.Value = Value
Exit Property
Else
Set e = e.nextEntry
End If
Else
Set e = e.nextEntry
End If
Wend
Du kannst das ... sehenSet...
ist dupliziert, und damit diese Frage.