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
Решение, которое я использовал для реализации короткого замыкания, является вложеннымIf
s
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...
дублируется, и поэтому этот вопрос.