Null Conditional in Powershell?

5.1k Views Asked by At

C# and other languages have null-conditionals usually ?.

A?.B?.Do($C);

Will not error out when A or B are null. How do I achieve something similar in powershell, what's a nicer way to do:

if ($A) {
  if ($B) {
    $A.B.Do($C);
  }
}
3

There are 3 best solutions below

0
On BEST ANSWER

PowerShell doesn't have the null-conditional operator, but it silently ignores property references on null-value expressions, so you can just "skip" to the method call at the end of the chain:

if($null -ne $A.B){
  $A.B.Do($C)
}

Works at any depth:

if($null -ne ($target = $A.B.C.D.E)){
    $target.Do($C)
}
0
On

As Mathias R. Jessen's answer points out, PowerShell by default has null-conditional access behavior (null-soaking) with respect to property access[1]; e.g., $noSuchVar.Prop quietly returns $null

js2010's answer shows the related null-coalescing operator (??) / null-conditional-assignment operators (??=), which are available in PowerShell [Core] v 7.1+

However, up to PowerShell 7.0:

  • There is no way to null-conditionally ignore method calls: $noSuchVar.Foo() always fails.

  • Similarly, there's no way to null-conditionally ignore (array) indexing: $noSuchVar[0] always fails.

  • If you opt into more rigorous behavior with Set-StrictMode, even the property-access null-soaking is no longer an option: with Set-StrictMode -Version 1 or higher, $noSuchVar.Prop results in an error.

In PowerShell [Core] 7.1+, null-conditional (null-soaking) operators are available:

The new operators:

  • have the same form as in C# in principle: ?. and ?[...]

  • but - as of v7.1 - require enclosing the variable name in {...}

That is, you currently cannot use just $noSuchVar?.Foo(), $A?.B, or $A?[1], you have to use
${noSuchVar}?.Foo(), ${A}?.B, or ${A}?[1]

The reason for this cumbersome syntax is that there are backward-compatibility concerns, because ? is a legitimate character in variable names, so hypothetical existing code such as $var? = @{ one = 1}; $var?.one could break without using the {...} to disambiguate the variable name; in practice, such use is vanishingly rare.

If you think that not encumbering the new syntax is more important than potentially breaking scripts with variable names ending in ?, make your voice heard at this GitHub issue.


[1] PowerShell's default behavior even offers existence-conditional property access; e.g., $someObject.NoSuchProp quietly returns $null.

2
On

Powershell 7 Preview 5 has operators that deal with nulls. https://devblogs.microsoft.com/powershell/powershell-7-preview-5/

$a = $null

$a ?? 'is null' # return $a or string if null
is null

$a ??= 'no longer null'  # assign if null

$a ?? 'is null'
no longer null

EDIT: Powershell 7 Preview 6 piles on more new operators: https://devblogs.microsoft.com/powershell/powershell-7-preview-6/. Since variable names can have a '?' in the name, you have to surround the variable name with curly braces:

${A}?.${B}?.Do($C)