Param(
[String] $foo
)
$foo ??= "bar" # does not work
$foo = $foo ?? "bar" # does not work
$foo = $foo ? $foo : "bar" # works
write-host $foo
I am using Powershell 7.4.5
What am I doing wrong here?
The following script without parameters works just fine:
$foo=$null
$foo ??= "bar"
Write-Host $foo
The problem seems to be the way Powershell handles string parameters in scripts. When omitting a string parameter or setting its default value to $null, Powershell will convert the value to an empty string (see How can I prevent a string argument changing from null to empty when bound to a parameter?).
Consider the following script:
Param(
[String]
$foo
)
if ($null -eq $foo) {
Write-Host "The parameter 'foo' is null."
} else {
Write-Host "The parameter 'foo' is not null."
}
if ("" -eq $foo) {
Write-Host "The parameter 'foo' is an empty string."
} else {
Write-Host "The parameter 'foo' is not an empty string."
}
Running the script:
PS C:\src\dummy-6\scripts> .\my-script.ps1 -foo $null
The parameter 'foo' is not null.
The parameter 'foo' is an empty string.
PS C:\src\dummy-6\scripts> .\my-script.ps1
The parameter 'foo' is not null.
The parameter 'foo' is an empty string.
PS C:\src\dummy-6\scripts>
Even if you set the default value of the parameter to $null it won't work as expected.
Also, the AllowNull validation attribute doesn't work if the type converter is set to string as the string type won't accept a null value.
Changing slightly the script:
Param(
[String]
[AllowNull()]
$foo=$null
)
if ($null -eq $foo) {
Write-Host "The parameter 'foo' is null."
} else {
Write-Host "The parameter 'foo' is not null."
}
if ("" -eq $foo) {
Write-Host "The parameter 'foo' is an empty string."
} else {
Write-Host "The parameter 'foo' is not an empty string."
}
Running the script:
PS C:\src\dummy-6\scripts> .\my-script.ps1
The parameter 'foo' is not null.
The parameter 'foo' is an empty string.
PS C:\src\dummy-6\scripts> .\my-script.ps1 -foo $null
The parameter 'foo' is not null.
The parameter 'foo' is an empty string.
[string] $foo = $null in the body of a function of a script stores the empty string too.If you set it to string, powershell is likely interpreting it as an empty string. You need to do this
if ([string]::IsNullOrEmpty($foo)) {
$foo = "bar"
}
$foojust never happens to be$null$null, but on coercing the first operand to a Boolean (which PowerShell implicitly supports for instances of any data type). Thus, given the - undoubtedly surprising - coercion of$nullto''(the empty string) when assigning to[string]-typed (parameter) variables, your ternary expression is the equivalent of'' ? '' : "bar", which predictably yiels"bar", given that''is coerced to$false(whereas any non-empty string is$true).