powershellnull-coalescing-operator

Null coalescing in powershell


Is there a null coalescing operator in powershell?

I'd like to be able to do these c# commands in powershell:

var s = myval ?? "new value";
var x = myval == null ? "" : otherval;

Solution

  • Powershell 7+

    Powershell 7 introduces native null coalescing, null conditional assignment, and ternary operators in Powershell.

    Null Coalescing

    $null ?? 100    # Result is 100
    
    "Evaluated" ?? (Expensive-Operation "Not Evaluated")    # Right side here is not evaluated
    

    Null Conditional Assignment

    $x = $null
    $x ??= 100    # $x is now 100
    $x ??= 200    # $x remains 100
    

    Ternary Operator

    $true  ? "this value returned" : "this expression not evaluated"
    $false ? "this expression not evaluated" : "this value returned"
    

    Previous Versions:

    No need for the Powershell Community Extensions, you can use the standard Powershell if statements as an expression:

    variable = if (condition) { expr1 } else { expr2 }
    

    So to the replacements for your first C# expression of:

    var s = myval ?? "new value";
    

    becomes one of the following (depending on preference):

    $s = if ($myval -eq $null) { "new value" } else { $myval }
    $s = if ($myval -ne $null) { $myval } else { "new value" }
    

    or depending on what $myval might contain you could use:

    $s = if ($myval) { $myval } else { "new value" }
    

    and the second C# expression maps in a similar way:

    var x = myval == null ? "" : otherval;
    

    becomes

    $x = if ($myval -eq $null) { "" } else { $otherval }
    

    Now to be fair, these aren't very snappy, and nowhere near as comfortable to use as the C# forms.

    You might also consider wrapping it in a very simple function to make things more readable:

    function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }
    
    $s = Coalesce $myval "new value"
    

    or possibly as, IfNull:

    function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }
    
    $s = IfNull $myval "new value" $myval
    $x = IfNull $myval "" $otherval
    

    As you can see a very simple function can give you quite a bit of freedom of syntax.

    UPDATE: One extra option to consider in the mix is a more generic IsTrue function:

    function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }
    
    $x = IfTrue ($myval -eq $null) "" $otherval
    

    Then combine that is Powershell's ability to declare aliases that look a bit like operators, you end up with:

    New-Alias "??" Coalesce
    
    $s = ?? $myval "new value"
    
    New-Alias "?:" IfTrue
    
    $ans = ?: ($q -eq "meaning of life") 42 $otherval
    

    Clearly this isn't going to be to everyone's taste, but may be what you're looking for.

    As Thomas notes, one other subtle difference between the C# version and the above is that C# performs short-circuiting of the arguments, but the Powershell versions involving functions/aliases will always evaluate all arguments. If this is a problem, use the if expression form.