6

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.

4

2 回答 2

2

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

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

于 2018-07-16T02:37:09.970 回答
0

$null 和 "" 之间的区别

空字符串不等于null;您需要专门为此进行测试。Null 是一个对象的不存在,而字符串是一个对象,即使它是空的。

这是 PowerShell 中的常见问题。无论出于何种原因,它都不允许您将 $null 值分配给字符串变量(或将字符串参数分配给 .NET 类型);它被转换为空字符串。当调用 .NET 方法以不同方式处理空字符串和空字符串时,这可能会引起一些头痛,这就是为什么他们后来添加了(在 v3 中,如果我没记错的话)[System.Management.Automation.NullString] 类。如果你想调用这样的方法,你可以这样做:

[SomeClass]::SomeMethod([nullstring]::Value)

[字符串]$camp = $null

将 $Null 分配给 $Camp,但由于 [string] 部分强制 $camp 为字符串类型,$Camp 将被分配 [String]$Null 的值

[String]$Null 将强制将 $Null(基本上是一个不存在的对象)转换为字符串,并在 PowerShell 中导致空字符串。

就 PowerShell 而言,这基本上是正确的。但是,在 .NET Framework 中,字符串确实可以为空,并且空字符串引用和空字符串之间存在区别。有时,当您查看 .NET 文档并想知道为什么它似乎无法在 PowerShell 中正常工作时,这会导致混淆。

使用 [字符串]::IsNullOrEmpty($variable)

https://powershell.org/forums/topic/difference-between-null-and/

也可以看看...

如何在 PowerShell 中检查字符串是否为空或为空?[字符串]::IsNullOrEmpty(...)

如何在 PowerShell 中检查字符串是否为空或为空?

* 更新 *

将您的代码更改为此...

function demo {
    param(
        [string]$value
    )

    if ([string]::IsNullOrEmpty($value))
    {
        "NULL"
    } elseif ($value -eq '') {
        "EMPTY"
    } else {
        "$value"
    }
}

无论是否进行调试(在“NULL”和“EMPTY”上设置断点),返回的结果在我的系统 ISE/VSCode 上都是相同的

# Results 

demo
NULL

demo -value ''
NULL

demo -value ' '


demo -value test
test

* 修改以显示 elseif 处理空格 *

有或有上述条件

 function demo {
    param(
        [string]$value
    )

    if ([string]::IsNullOrEmpty($value))
    {
        "NULL"
    } elseif ([string]::IsNullOrWhiteSpace($value)) {
        "EMPTY or a White Space"
    } else {
        "$value"
    }
}

# Results

demo
NULL
demo -value ''
NULL
demo -value ' '
EMPTY or a White Space
demo -value test
test
于 2018-07-11T23:50:57.727 回答