PowerShell inline If (IIf)

iRon picture iRon · Sep 5, 2014 · Viewed 79.8k times · Source

How do I create an a statement with an inline If (IIf, see also: Immediate if or ternary If) in PowerShell?

If you also think that this should be a native PowerShell function, please vote this up: https://connect.microsoft.com/PowerShell/feedback/details/1497806/iif-statement-if-shorthand

Update (7 October 2019)

The Microsoft Connect is retired, but the good news is that support for a ternary operator in PowerShell (Core) language appears to be on it's way...

Answer

iRon picture iRon · Sep 5, 2014

You can use the PowerShell’s native way:

"The condition is " + (&{If($Condition) {"True"} Else {"False"}}) + "."

But as this adds a lot of parenthesis and brackets to your syntax, you might consider the following (probably one of the smallest existing) CmdLet:

Function IIf($If, $Right, $Wrong) {If ($If) {$Right} Else {$Wrong}}

Which will simplify your command to:

"The condition is " + (IIf $Condition "True" "False") + "."

Added 2014-09-19:

I have been using the IIf cmdlet now for a while, and I still think it will make syntaxes more readable in a lot of cases, but as I agree with Jason’s note about the unwanted side effect that both possible values will be evaluated even obviously only one value is used, I have changed the IIf cmdlet a bit:

Function IIf($If, $IfTrue, $IfFalse) {
    If ($If) {If ($IfTrue -is "ScriptBlock") {&$IfTrue} Else {$IfTrue}}
    Else {If ($IfFalse -is "ScriptBlock") {&$IfFalse} Else {$IfFalse}}
}

Now you might add a ScriptBlock (surrounded by {}'s) instead of an object which will not be evaluated if it is not required as shown in this example:

IIf $a {1/$a} NaN

Or placed inline:

"The multiplicative inverse of $a is $(IIf $a {1/$a} NaN)."

In case $a has a value other than zero, the multiplicative inverse is returned; otherwise, it will return NaN (where the {1/$a} is not evaluated).

Another nice example where it will make a quiet ambiguous syntax a lot simpler (especially in case you want to place it inline) is where you want to run a method on an object which could potentially be $Null.

The native ‘If’ way to do this, would be something like this:

If ($Object) {$a = $Object.Method()} Else {$a = $null}

(Note that the Else part is often required in e.g. loops where you will need to reset $a.)

With the IIf cmdlet it will look like this:

$a = IIf $Object {$Object.Method()}

(Note that if the $Object is $Null, $a will automatically be set to $Null if no $IfFalse value is supplied.)


Added 2014-09-19:

Minor change to the IIf cmdlet which now sets the current object ($_ or $PSItem):

Function IIf($If, $Then, $Else) {
    If ($If -IsNot "Boolean") {$_ = $If}
    If ($If) {If ($Then -is "ScriptBlock") {&$Then} Else {$Then}}
    Else {If ($Else -is "ScriptBlock") {&$Else} Else {$Else}}
}

This means you can simplify a statement (the PowerShell way) with a method on an object that could potentially be $Null.

The general syntax for this will now be $a = IIf $Object {$_.Method()}. A more common example will look something like:

$VolatileEnvironment = Get-Item -ErrorAction SilentlyContinue "HKCU:\Volatile Environment"
$UserName = IIf $VolatileEnvironment {$_.GetValue("UserName")}

Note that the command $VolatileEnvironment.GetValue("UserName") will normally result in an "You cannot call a method on a null-valued expression." error if the concerned registry (HKCU:\Volatile Environment) doesn’t exist; where the command IIf $VolatileEnvironment {$_.GetValue("UserName")} will just return $Null.

If the $If parameter is a condition (something like $Number -lt 5) or forced to a condition (with the [Bool] type), the IIf cmdlet won't overrule the current object, e.g.:

$RegistryKeys | ForEach {
    $UserName = IIf ($Number -lt 5) {$_.GetValue("UserName")}
}

Or:

$RegistryKeys | ForEach {
    $UserName = IIf [Bool]$VolatileEnvironment {$_.OtherMethod()}
}

Added 2020-03-20:

Using the ternary operator syntax

PowerShell 7.0 introduced a new syntax using the ternary operator. It follows the C# ternary operator syntax:

The ternary operator behaves like the simplified if-else statement. The <condition> expression is evaluated and the result is converted to a boolean to determine which branch should be evaluated next:

The <if-true> expression is executed if the <condition> expression is true The <if-false> expression is executed if the <condition> expression is false

Example:

"The multiplicative inverse of $a is $($a ? (& {1/$a}) : 'NaN')."