Powershell treats empty string as equivalent to null in switch statements but not if statements

11,401

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"}}
Share:
11,401
Richiban
Author by

Richiban

Into my C#, F# and Powershell

Updated on June 24, 2022

Comments

  • Richiban
    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 a switch statement but not in an if 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
    Tim Sparkles about 11 years
    This 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
    Bacon Bits almost 9 years
    Also 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
    Richiban about 8 years
    Amazingly, the second block of your code executes two branches of the switch statement... It prints out both "null" and "empty string"!
  • Christopher G. Lewis
    Christopher G. Lewis over 7 years
    This 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
    Zastai about 6 years
    Not so amazing - no break statement, so execution falls through to the next case.
  • Zastai
    Zastai about 6 years
    Oh 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
    New Guy about 3 years
    This 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" } }