37
#Requires -Version 2.0

[CmdletBinding()]
Param(
  [Parameter()] [string] $MyParam = $null
)

if($MyParam -eq $null) {
  Write-Host 'works'
} else {
  Write-Host 'does not work'
}

Outputs "does not work" => looks like strings are converted from null to empty string implicitly? Why? And how to test if a string is empty or really $null? This should be two different values!

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
D.R.
  • 20,268
  • 21
  • 102
  • 205

5 Answers5

40

Okay, found the answer @ https://www.codykonior.com/2013/10/17/checking-for-null-in-powershell/

Assuming:

Param(
  [string] $stringParam = $null
)

And the parameter was not specified (is using default value):

# will NOT work
if ($null -eq $stringParam)
{
}

# WILL work:
if ($stringParam -eq "" -and $stringParam -eq [String]::Empty)
{
}

Alternatively, you can specify a special null type:

Param(
  [string] $stringParam = [System.Management.Automation.Language.NullString]::Value
)

In which case the $null -eq $stringParam will work as expected.

Weird!

Andrew Savinykh
  • 25,351
  • 17
  • 103
  • 158
D.R.
  • 20,268
  • 21
  • 102
  • 205
  • 2
    Please note that in PowerShell you should really use `if ($null -eq $value)` instead of `if ($value -eq $null)`. The PowerShell Script Analyser module warns for this as well. See https://www.spcaf.com/blog/powershell-null-comparison/ – oɔɯǝɹ May 13 '16 at 10:56
  • Or better yet `if ([String::IsNullOrEmpty($stringParam)])`, which changes the behavior slightly (for the better imo), but reads nicely and eliminates the issue of order. Regardless, thanks, this helped me a ton. – Lee Richardson Oct 24 '19 at 18:52
14

You will need to use the AllowNull attribute if you want to allow $null for string parameters:

[CmdletBinding()]
Param (
    [Parameter()] 
    [AllowNull()]
    [string] $MyParam
)

And note that you should use $null on the left-hand side of the comparison:

if ($null -eq $MyParam)

if you want it to work predictably

oɔɯǝɹ
  • 7,219
  • 7
  • 58
  • 69
3

seeing many equality comparisons with [String]::Empty, you could use the [String]::IsNullOrWhiteSpace or [String]::IsNullOrEmpty static methods, like the following:

param(
    [string]$parameter = $null
)

# we know this is false
($null -eq $parameter)

[String]::IsNullOrWhiteSpace($parameter)
[String]::IsNullOrEmpty($parameter)
('' -eq $parameter)
("" -eq $parameter)

which yields:

PS C:\...> .\foo.ps1
False
True
True
True
True
Scottley
  • 91
  • 5
  • This answer doesn't really address any of the remarks in the question (ie. explanation of the behavior when assigning `$null` to a `[string]` parameter) – Mathias R. Jessen Aug 17 '16 at 01:01
  • I thought I answered the question: "And how to test if a string is empty or really $null?" – Scottley Sep 08 '16 at 19:45
3

Simply do not declare the param's type if you want a $null value to remain:

Param(
    $stringParam
)

(None of the other solutions worked for me when declaring the type.)

argonym
  • 853
  • 7
  • 13
  • Switch to javascript-style declaration and comparison when it comes to strings I suppose (unfortunately). All the rest of this post seems to reflect powershell baggage. – dudeNumber4 Mar 22 '19 at 13:55
1

So it seems a default value of $null for parameters of type [string] defaults to empty string, for whatever reason.

Option 1

if ($stringParam) { ... }

Option 2

if ($stringParam -eq "") { ... }

Option 3

if ($stringParam -eq [String]::Empty) { ... }
angularsen
  • 8,160
  • 1
  • 69
  • 83