首页 > 解决方案 > 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.

标签: powershelldebuggingbreakpointsnull-string

解决方案


PetSerAl和以前一样多次在对该问题的评论中提供了关键指针:

一个已知的优化错误是最可能的原因(从 Windows PowerShell v5.1 / PowerShell Core v6.1.0 开始),当代码在 Visual Studio Code 或 ISE调试器中运行时,该错误恰好被屏蔽

因此,您可以使用链接的错误报告中提到的相同解决方法Remove-Variable:调用函数体中的任何位置(它的存在就足够了 - 实际上不需要在运行时进行调用):

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

现在"NULL",无论是否调试,您都能始终如一地获得输出。

但是,最好将使用限制[NullString]::Value在它的设计用途:传递null.NET 方法string的-typed 参数- 见下文。


至于为什么需要使用 of[NullString]::Value来传递$null给字符串参数/存储$null[string]变量中,因为 .NET 字符串通常可以直接存储null( $null):

根据(历史)设计,当您将 PowerShell分配给变量时,它会转换$null为(空字符串);这是理由:''[string]

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

设计背后的想法是,在大多数 $null 情况下,空字符串都表示相同的错误条件,并且在区别很重要的极少数情况下, $PSBoundParameters足以区分是否知道提供了值。

鉴于在将参数传递给-typed .NET 方法时,即使$null 直接传递也会执行转换''string,因此您无法传递null到 v2 之前的此类方法。
为了解决这个问题,版本 3 引入了[NullString]::Value,它明确表示希望传递$null字符串上下文。
(替代方案 - 使 PowerShell 字符串默认$null并允许直接分配$null- 被认为是会破坏太多现有脚本的更改。)

考虑到 PowerShell 不希望变量包含在其他上下文中,使用 [NullString]::Value超出其预期目的(即,传递null给.NET 方法中的参数)是有问题的。string[string]$null

修复上述优化错误将有助于解决问题中的情况,但可能还有其他陷阱。


推荐阅读