Using Null Coalescing Operator in PowerShell 7

PowerShell 7 has been around for some time now, with Microsoft and community working on version 7.2. One of the new exciting features introduced in PowerShell 7 is null-coalescing operator i.e. ?? operator. If you have been working on the PowerShell actively, you may have seen situation where you get a null variable from an assignment. More often than not, its because the cmdlet on right side does not returned anything because of whatsoever reasons. Also by default, variables are assigned $null, when not initialized.

Life Before PowerShell 7

Before PowerShell, we have to use a if..else condition or just if.. condition, to check if variable is null and then proceed accordingly.

For example, below code would result in output of It's a null!. It is because by default, variables are assigned $null:

$my_var
if($null -eq $my_var){
    Write-Host "It's a null!"
}
else{
    Write-Host "Not a null!"
}

Let’s assign $my_var some output and then run the above code. It will result in output of Not a null!:

$my_var=$true
if($null -eq $my_var){
    Write-Host "It's a null!"
}
else{
    Write-Host "Not a null!"
}

Life with PowerShell 7+

PowerShell 7 introduces null coalescing operator (??) to make it easy to identify the variable or expression on the left side is null or not. If it’s null, then right side of the operator gets executed:

<left> ?? <right>

So, the first example can be simply re-written using a simple expression like:

$my_var ?? (Write-Host "It's a null!")

If left-side expression or variable evaluates to not null, then right-side does not gets executed at all. For example, in below expression, right-side code never gets executed:

($my_var = $true) ?? (Write-Host "It's a null!" )

Example of real-life use cases

Note that the left-side and right side of null coalescing operator can be both expressions. The left-side just needs to be evaluated to null. However, if we are using expressions, make sure to wrap them with a parentheses operator (). Below are some of the real-life examples:

# Check if log file exists. If not, create it. 
(Get-Item D:\log_file.log -ErrorAction SilentlyContinue) ?? 
(New-Item -ItemType File -Path D:\log_file.txt)

# Check if user 'TestUser' is present in 'Administrators' group. If not, add it. 
(Get-LocalGroupMember -Name Administrators -Member TestUser -ErrorAction SilentlyContinue) ??
(Add-LocalGroupMember -Name Administrators -Member TestUser)

# Check if Az module is installed. If not, install it
(Get-Module -Name 'Az' -ListAvailable) ??
(Install-Module -Name 'Az')

# Check if Az module is loaded. If not, import it in current session.
(Get-Module -Name 'Az') ??
(Import-Module -Name 'Az')

# Check if notepad process is running. If not, start it. 
(Get-Process -Name notepad -ErrorAction SilentlyContinue) ??
(Start-Process -FilePath C:\Windows\System32\notepad.exe)

Also note that, in the left-side of the expression, we have suppressed error output using ErrorAction switch. You may or may not use it, depending on your preference.

Stretching Use-Cases

You are not limited to a single one liner inside either the left or right side of the coalescing operator, but you must wrap your code between curly braces {} and preceded by an ampersand &.

For example, consider below code:

# this does not work 
($var = $null) ?? (Write-Host "Executing first command"; Write-Host "Executing second command")

# this works 
($var = $null) ?? (&{Write-Host "Executing first command"; Write-Host "Executing second command"})

Pipeline operator seems to work fine using both scenarios i.e. with or without & operator. Consider below code:

# this works 
($var = $null) ?? (&{1..3 | ForEach-Object {Write-Host $_}})

# this works
($var = $null) ?? (1..3 | ForEach-Object {Write-Host $_})

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s