tags:

views:

64

answers:

1

Working on a Powershell script I had several places where I wanted A unless it was null, else B. Essentially the ?? operator in C#. I ended up writing the function shown below, but I can't help but think there is a built-in way to do this.

Is there a better, built-in, way?

function Get-ValueOrDefault()
{
    foreach ($value in $args)
    {
        if ($value -ne $null) { return $value }
    }
}

I think this works better:

function Get-ValueOrDefault() { $args | select -first 1 }
+2  A: 

This is what we provide in the PowerShell Community Extensions:

<#
.SYNOPSIS
    Similar to the C# ?? operator e.g. name = value ?? String.Empty
.DESCRIPTION
    Similar to the C# ?? operator e.g. name = value ?? String.Empty;
    where value would be a Nullable&lt;T&gt; in C#.  Even though PowerShell
    doesn't support nullables yet we can approximate this behavior.
    In the example below, $LogDir will be assigned the value of $env:LogDir
    if it exists and it's not null, otherwise it get's assigned the
    result of the second script block (C:\Windows\System32\LogFiles).
    This behavior is also analogous to Korn shell assignments of this form:
    LogDir = ${$LogDir:-$WinDir/System32/LogFiles}
.PARAMETER PrimaryExpr
    The condition that determines whether the TrueBlock scriptblock is used or the FalseBlock
    is used.
.PARAMETER AlternateExpr
    This block gets evaluated and its contents are returned from the function if the Conditon
    scriptblock evaluates to $true.
.EXAMPLE
    C:\PS> $LogDir = ?? {$env:LogDir} {"$env:windir\System32\LogFiles"}
    $LogDir is set to the value of $env:LogDir unless it doesn't exist, in which case it 
    will then default to "$env:windir\System32\LogFiles".
#>
filter Invoke-NullCoalescing {
    param([scriptblock]$PrimaryExpr   = $(throw "Parameter '-primaryExpr' (position 1) required"), 
          [scriptblock]$AlternateExpr = $(throw "Parameter '-alternateExpr' (position 2) required"))

    if ($primaryExpr -ne $null) {
        $result = &$primaryExpr
        if ($result -ne $null -and "$result" -ne '') {
            $result
        }
        else {
            &$alternateExpr
        }
    }
    else {
        &$alternateExpr
    }
}

New-Alias ?? Invoke-NullCoalescing

PS> ?? {$xyzzy} {"empty"}
empty

PS> ?? {$psversiontable} {"empty"}

Name                           Value
----                           -----
CLRVersion                     2.0.50727.4927
BuildVersion                   6.1.7600.16385
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1
Keith Hill
Is there something that PSCX don't provide? ;)
stej
Oh yeah, there's room for new stuff. :-)
Keith Hill
I'm not accepting this answer because I was looking for something that doesn't require defining any new functions, is visually pleasing, and whose purpose is fairly obvious to someone reading the script.
OldFart
There is no built in way how to do that. So you need to define a function.
stej
There is a suggestion to add a ternary operator (bool_expr ? true_expr : false_expr) to the language. You can vote on it here - https://connect.microsoft.com/PowerShell/feedback/details/53059/add-ternary-operator-to-script-language#
Keith Hill
Wow, that's pretty old suggestion :| Voted.
stej