IIf function evaluates both of its result arguments
ID |
vbnet.performance.avoid_iif |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Performance |
Language |
VB.NET |
Description
Reports calls to the legacy IIf function, which selects between two values at run time.
Unlike the If operator it is an ordinary function call, so the arguments for both the true
part and the false part are evaluated before the selection is made.
Rationale
Because both result arguments are always evaluated, IIf pays for work it then discards, and
the condition does not protect the branch it appears to guard:
IIf(count > 0, total / count, 0) still performs the division when count is zero, and
IIf(o Is Nothing, "", o.Name) still dereferences o and throws a NullReferenceException.
The parameters and the result are typed Object, so every value type is boxed - an extra
allocation per call - and no compile-time type checking is applied to either branch.
The following code illustrates the pattern detected by this rule:
Public Function DiscountRate(ByVal isPremium As Boolean) As Double
' FLAGGED: IIf function evaluates both of its result arguments
Return CDbl(IIf(isPremium, 0.15, 0.0))
End Function
Remediation
Use the If operator, which short-circuits and evaluates only the branch it returns, keeps
the static type of the operands, and does not box. For longer branches use a plain
If … Then … Else statement.
' Before: the division runs even when count is 0
Return CDbl(IIf(count > 0, total / count, 0.0))
' After: only the selected branch is evaluated
Return If(count > 0, total / count, 0.0)