Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does [NullString]::Value evaluate differently with a breakpoint?

I've tried this code in PowerShell ISE and VS Code with the same strange result. Without a breakpoint, the output is EMPTY, but with a breakpoint in the line with "NULL", the output is NULL (as expected). Why?

function demo {
    param(
        [string] $value = [NullString]::Value
    )

    if ($null -eq $value) {
        "NULL"
    } elseif ($value -eq '') {
        "EMPTY"
    } else {
        "$value"
    }
}

demo

I know now, that PowerShell will always convert a non-string value (e.g. $null or [NullString]::Value) to an (empty) string, when you use the type modifier [string] for a parameter. Fine, I can live with that, but it's hard to figure that out by yourself, if debugging is so weird in this case.

like image 704
andiDo Avatar asked Jul 11 '18 21:07

andiDo


People also ask

What is the difference between null and empty string?

The Java programming language distinguishes between null and empty strings. An empty string is a string instance of zero length, whereas a null string has no value at all. An empty string is represented as "" . It is a character sequence of zero characters.

Is null and empty the same in Javascript?

The value null represents the absence of any object, while the empty string is an object of type String with zero characters. If you try to compare the two, they are not the same.

How do you check string is empty or not in PowerShell?

To check if the file is empty using PowerShell, we can use the string method called IsNullorWhiteSpace(). This method provides result true if the file is empty or only contains the white spaces otherwise false.

Can we assign null to string in Java?

In Java, null is neither an Object nor a type. It is a special value that we can assign to any reference type variable. We can cast null into any type in which we want, such as string, int, double, etc. Let's take an example to understand how we can assign null values to any reference type.


1 Answers

PetSerAl, as many times before, has provided the crucial pointer in a comment on the question:

A known optimization bug is the most likely cause (as of Windows PowerShell v5.1 / PowerShell Core v6.1.0), and that bug just happens to be masked when the code is run in the Visual Studio Code or ISE debugger.

You can therefore use the same workaround mentioned in the linked bug report: place a call to Remove-Variable anywhere in the function body (its presence is enough - the call needn't actually be made at runtime):

function demo {
    param(
        [string] $value = [NullString]::Value
    )

    # Workaround for optimization bug
    if ($False) { Remove-Variable }

    if ($null -eq $value) {
        "NULL"
    } elseif ($value -eq '') {
        "EMPTY"
    } else {
        "$value"
    }
}

demo

Now you consistently get "NULL" as the output, whether debugging or not.

However, it's best to restrict use of [NullString]::Value to what it was designed for: passing null to string-typed parameters of .NET methods - see below.


As for why use of [NullString]::Value is needed at all in order to pass $null to a string parameter / store $null in a [string] variable, given that .NET strings can normally store null ($null) directly:

By (historical) design, PowerShell converts $null to '' (the empty string) when you assign it to a [string] variable; here's the rationale:

From https://github.com/PowerShell/PowerShell/issues/4616#issuecomment-323530442:

The thinking behind the design was that in most ways, $null and the empty string both represent the same error condition and that in the rare case where a distinction was important, $PSBoundParameters would be sufficient to distinguish between knowing a value was provided or not.

Given that even passing $null directly performs conversion to '' when passing arguments to string-typed .NET methods, you couldn't pass null to such methods up to v2.
To remedy that, version 3 introduced [NullString]::Value, which explicitly signals the desire to pass $null in a string context.
(The alternative - making PowerShell strings default to $null and allowing direct assignment of $null - was considered a change that would break too many existing scripts.)

Using [NullString]::Value beyond its intended purpose - i.e., for passing null to string parameters in .NET methods - is problematic, given that PowerShell doesn't expect [string] variables to contain $null in other contexts.

Fixing the above-mentioned optimization bug would help in the scenario in the question, but there may be other pitfalls.

like image 182
mklement0 Avatar answered Sep 22 '22 16:09

mklement0