VB.NET - IIF (,) - оцениваются обе "стороны". В каких ситуациях я должен следить?
Недавно я узнал о функции IIF (A, B, C). Я долгое время VB/VB.NET Coder, который недавно потратил много времени на ускорение в SQL-кодировании.
Одна (очевидная) общая вещь, которую нужно делать в SQL, выглядит примерно так:
select (case where @var = 0 then MyTable.Val1 else MyTable.Val2 end) from MyTable
IIF (A, B, C) позволит мне сделать это в VB.NET... все на одной строке.
Однако я прочитал, что оба B и C оцениваются независимо от того, что оценивает A.
Я могу думать о некоторых очевидных ситуациях, когда это плохо, например:
Dim X as integer = IIF(SomeBoolean = true, ExpensiveFunction1(), ExpensiveFunction2())
Как я буду включать это в свой репертуар, есть ли еще более тонкие ситуации, когда я могу попасть в проблему с использованием IIF?
Это довольно большой отход в некоторых ситуациях от использования старомодного:
Dim X as integer
if SomeBoolean = true then
X = ExpensiveFunction1()
else
X = ExpensiveFunction2()
end if
Я надеюсь сохранить некоторые неприятные проблемы с производительностью и/или ошибки в будущем.
Обновление 2016
В течение последних нескольких лет существует новая функция VB.NET, которая исключает необходимость использования функции IIF().
if(Something = true, ExecuteA(), ExecuteB())
Выполняются только ExecuteA() или ExecuteB(). Наконец, встроенный IF с короткой циркуляцией.
Итак, если вы используете более поздние версии VB.NET(начиная с 2016 года), используйте это, если можете.
Ответы
Ответ 1
Вот наиболее распространенный вопрос.
Z = iif(y=0, 0, x/y) 'Throws a divide by zero exception when y is 0
Не используйте его, чтобы избежать деления на нулевые ошибки.
Другая возможная логическая ошибка заключается в том, что одна сторона iif или другого вызывает метод, который изменяет состояние системы или имеет выходные параметры.
Z = iif(FunctionA(InputOutputParam), FunctionB(InputOutputParam))
'InputOutputParam is indeterminate or at least ambiguous here.
В моем опыте действительно нет оснований использовать IIF. В основном это просто используется для сокращения кода и с учетом проблем, которые он может вызвать, но это просто не стоит. Плюс, я думаю, что это делает код более трудным для чтения.
Другая вещь, которая кусается, заключается в том, что она возвращает значение в виде бокса (то есть тип данных объекта), которое вы должны вернуть назад к нужному типу.
Ответ 2
[IIF
, not IFF
]
Наиболее распространенный случай, который мы видели, это то, что одна сторона или другая сторона оценивает Nothing
.
Возможно, ваш код будет использовать IIF
как защитник, чтобы не получить NullReferenceException
, например:
IIF(something Is Nothing, "nothing", something.Value)
Но это не сработает, потому что обе стороны всегда оцениваются. Это происходит в лоте в коде, написанном людьми, которые исходят из фона C/С++/С#/Java, поскольку на этих языках тернарный оператор ?:
выполняет оценку короткого замыкания.
И тот факт, что в документации VS 2005 IIF() указано, что IIF
точно так же, как ?:
не помогает:
Функция IIf предоставляет аналог тройного условного оператора:?: в Visual С++.
Нигде на этой странице ссылки не указано, что обе стороны оцениваются.
Ответ 3
Согласно MSDN, оператор "If", введенный в VB2008, будет иметь короткое замыкание, что было бы идеальным для вашего дорогостоящего случая вычислений:
http://msdn.microsoft.com/en-us/library/bb513985.aspx
Ответ 4
Ну, вы также должны убедиться, что в iif нет никаких функций, которые изменяют любые данные на основе условия. Мы используем If для этого довольно много. Это просто платит, чтобы вспомнить об iif.
Ответ 5
Я был вынужден использовать iif (для компактности кода), где у меня был кусок кода, который копировал значения из многих массивов в электронную таблицу, но "ничего" в массиве заставляет код выйти из подпрограммы (не сбой), поэтому я завернул строку в iif, чтобы проверить, не содержит ли ячейка массива - если это так, а затем передать обратно ", в противном случае передать ячейку массива (преобразование в строку 1-го).
Как сказано выше, еще одна причина не использовать iif.
Я все еще в трауре из-за отсутствия функции NZ, которую я использовал все время в MS Access.