Powershell treats empty string as equivalent to null in switch statements but not if statements
Solution 1
I think is a bug of powershell 2.0 (here some info on MSFT Connect).
I can say that in v 3.0 you code return out here!
Solution 2
Powershell auto-magically casts a $null to an empty string. Consequently, when using $null on a .NET API call, Powershell actually casts it to an empty string. To pass an actual null value in an API call, use [NullString]::Value instead.
Solution 3
The following statements show that $null
is not equivalent to the empty string in a switch statement.
$a=""; switch ($a){$null {"null"} "" {"empty string"}}
$a=$null; switch ($a){$null {"null"} "" {"empty string"}}
Comments
-
Richiban almost 2 years
Please tell me that I've got a subtle mistake in my code here and that this is not actually the way that Powershell operates.
$in = "" if ($in -ne $null) { switch ($in) { $null { echo "This is impossible" } default { echo "out here!" } } }
All good, honest logic says that this script should never print out "This is impossible". But it does, if $in is an empty string. So in Powershell it would appear that an empty string and a
null
string are considered equivalent in aswitch
statement but not in anif
statement. This is so confusing and is one of the main reasons many people shy away from using Powershell.Can anyone enlighten me as to why this is the case? Does anyone know what switch is actually doing behind the scenes? It's certainly not doing a straight -eq comparison.
-
Tim Sparkles about 11 yearsThis is only true if you coerce $null to a [string] value. This coercion happens implicitly when calling a function with an explicit string-typed parameter.
-
Bacon Bits almost 9 yearsAlso note that
[NullString]::Value -eq $null
returns False. You'll need to compare the string to[NullString]::Value
... which makes it often impractical. It's easier to use[string]::IsNullOrEmpty()
and[string]::IsNullOrWhiteSpace()
for string comparison, but that means''
is a null string. If you're working with SQL, this can make life complicated, especially because for that you'll often need to use[System.DBNull]::Value
, which is also not equal to$null
and not equal to[NullString]::Value
. -
Richiban about 8 yearsAmazingly, the second block of your code executes two branches of the switch statement... It prints out both "null" and "empty string"!
-
Christopher G. Lewis over 7 yearsThis is fantastic - I've spent hours with a class that was screwing up convertTo-Json by outputing an empty string instead of a null string.
-
Zastai about 6 yearsNot so amazing - no break statement, so execution falls through to the next case.
-
Zastai about 6 yearsOh great, how consistent. That's bound to be a common gotcha for new PowerShell users, especially since it's not how switch statements work elsewhere in the .NET ecosystem.
-
New Guy about 3 yearsThis is not true. The $null is being coerced into an empty string and matches both switch conditions. If you swap conditions in your second line you will see that both statements still print out. There is also no fall-through in PowerShell. The switch is merely matching any and all conditions. You would still need a break statement to force it to match only one condition.
$a = $null; switch ($a) { "" { "empty" } $null {"null"} "different" { "not matching" } }