VBA Короткое замыкание `И` Альтернативы [дубликаты]

На этот вопрос уже есть ответ:

AndAlso / OrElse в VBA 7 ответов

VBA не закорачивает

VBA не поддерживает короткое замыкание - очевидно, потому что оно имеет только побитовые операции И / или / Не и т. Д. От Спецификация языка VBA: «Логические операторы - это простые операторы данных, которые выполняют побитовые вычисления для своих операндов». В этом свете, имеет смысл, что VBA был разработан сtrue = &H1111 а такжеfalse = &H0000: таким образом логические операторы могут быть оценены как побитовые операции.

Отсутствие короткого замыкания может вызвать проблемы

Производительность:ReallyExpensiveFunction() всегда будет выполняться при вычислении этого оператора, даже если это не требуется в результате левой части условия

If IsNecessary() And ReallyExpensiveFunction() Then '... End If

Errors: если MyObj имеет значение Nothing, эта условная оценка приведет к ошибке времени выполнения, поскольку VBA все равно будет пытаться проверить значениеProperty

If Not MyObj Is Nothing And MyObj.Property = 5 Then '... End If

Решение, которое я использовал для реализации короткого замыкания, является вложеннымIfs

If cond1 And cond2 Then
    '...
End If

Становится

If cond1 Then
    If cond2 Then
        '...
    End If
End If

Таким образом, операторы If дают поведение, похожее на короткое замыкание, не мешая оценитьcond2 еслиcond1 являетсяFalse.

Если есть предложение Else, это создает дублирующие блоки кода

If Not MyObj Is Nothing And MyObj.Property = 5 Then
    MsgBox "YAY"
Else
    MsgBox "BOO"
End If

Становится

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

Есть ли способ переписатьIf заявления, чтобы сохранить поведение короткого замыкания, но избежать дублирования кода?

Возможно, с другим оператором ветвления, какSelect Case?

Чтобы добавить контекст к вопросу, вот конкретный случай, на который я смотрю. Я реализую хеш-таблицу, которая обрабатывает коллизии, связывая их в связанный список. Базовый размер массива принудительно равен степени двойки, и хэши распределяются по текущему размеру массива путем усечения их до соответствующей длины.

Например, предположим, что длина массива равна 16 (двоичный код 10000). Если у меня есть ключ, который хэширует до 27 (двоичный код 11011), я могу сохранить его в своем массиве из 16 слотов, сохраняя только биты в пределах ограничения этого размера массива. Индекс, в котором этот элемент будет храниться, равен(hash value) And (length of array - 1) который в данном случае является(binary 11011) And (1111) который1011, равное 11. Фактический хеш-код хранится вместе с ключом в слоте.

При поиске элемента в хэш-таблице в цепочке необходимо проверить и хэш, и ключ, чтобы определить, что был найден правильный элемент. Однако, если хеш не совпадает, то нет смысла проверять ключ. Я надеялся получить какое-то нематериальное количество производительности, вложив Ifs, чтобы получить поведение при коротком замыкании:

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

Ты можешь видетьSet... дублируется, и поэтому этот вопрос.

Ответы на вопрос(3)

Ваш ответ на вопрос