VBA Short-Circuit `And` Alternatives [duplizieren]

Diese Frage hat hier bereits eine Antwort:

AndAlso / OrElse in VBA 7 answers

VBA 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 verschachteltIfs

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.

Antworten auf die Frage(3)

Ihre Antwort auf die Frage