【问题标题】:Object-Property assigned $null does not test true for $null分配给 $null 的对象属性不测试 $null 是否为真
【发布时间】:2020-12-16 11:08:16
【问题描述】:

我已经开始使用 PowerShell 来完成一些事情,并在 PowerShell 中使用变量 $null

我遇到的问题是,当我将变量$null 分配给类中定义的变量时,测试返回false 而不是true

示例代码:

class test {
    [string]$test1
}

$test = [test]::new()

$test.test1 = $null

$null -eq $test2 # tests true

$null -eq $test.test1 # tests false

现在,未定义变量 $test2 的测试返回 true,因为 PowerShell 中的每个未定义变量都被分配了 $null

但是,如果我测试我分配给$null 的对象test1 的属性test1 测试false$null

是不是因为在 PowerShell 中$null 是一个值为$null 的对象,而现在该对象的属性不是$null,因为它分配了一个空值的对象$null

我已经阅读了 Microsoft "Everything you wanted to know about $null" 的文档,但它并没有启发我。

如果我不初始化变量,那么它将测试true 是否为$null

【问题讨论】:

    标签: powershell


    【解决方案1】:

    $test.test1 不是$null,它是空字符串(因为您明确将其值定义为[string]):

    C:\> $test.test1.GetType()
    
    IsPublic IsSerial Name                                     BaseType
    -------- -------- ----                                     --------
    True     True     String                                   System.Object
    

    证明:

    C:\> $test.test1 -eq ""
    True
    

    【讨论】:

      【解决方案2】:

      如果您使用type contstraint (如[string][int]),Powershell 会使用默认的约束类型初始化null-assignment 的成员。

      正如@robdy 在上述答案中所说,您要么检查类型默认值,要么删除约束。

      如果您使用 [int] 类型约束,这可能会变得更加明显:

      class test {
          [int]$i1 = 42
      }
          
      $test = [test]::new()
      Write-Host $test.i1
      $test.i1 = $null
      Write-Host $test.i1
          
      

      输出:

      42
      0
      

      【讨论】:

        【解决方案3】:

        详述robdy's helpful answer

        • 根据设计,PowerShell 中的[string] 类型变量、参数变量和自定义类属性不存储$null[1],仅存储实际字符串价值观。 分配$null 总是转换为''(空字符串)。

          • 下面,$var 接收 '',而不是 $null,因为是 [string] 类型的;因此,第一个 -eq 测试失败,第二个成功。

          • [string] $var = $null; $null -eq $var; '' -eq $var

          • 请注意,其他 .NET 引用类型(与值类型相反,它基本上不能为空)在 PowerShell 中受到影响;也就是说,您可以$null 分配给他们。值得注意的是,这也适用于[object]。请注意,not 对变量/参数/属性进行类型约束与[object]-键入它相同。

        • PowerShell class 中的未初始化 [string] 属性 目前默认为$null 应该被视为一个错误 em> - 见GitHub issue #7294

          • 如果您显式初始化为$null,则不一致会变得很明显,这会再次转换为''并导致测试失败。

          • class test { [string]$test1=$null }; $null -eq [test]::new().test1

          • 如果该错误已修复并且您确实需要在 [string] 类型的属性中使用 $null 值 - 这在 PowerShell 代码的上下文中是不明智的 - 您必须使用 [NullString]::Value,如图所示在下面链接的答案中:
            class test { [string]$test1 = [NullString]::Value }; $null -eq [test]::new().test1

        如需了解更多信息,请参阅this answer


        [1] 无法存储 $nullPowerShell 为了简化而施加的限制。底层 .NET 类型 System.String 通常在其他语言中没有此限制,尤其是在 C# 中。

        【讨论】:

        • 这是引起我注意的一件事。但我认为会是这样,因为你没有初始化变量,所以它没有类型约束或任何东西,因为它是$null。如以下示例:class test { [string]$test1 } $test = [test]::new() $test.test1 $null -eq $test2 # tests true $null -eq $test.test1 # tests true $test.test1 | gm #comes back with an error "gm : You must specify an object for the Get-Member cmdlet"
        • @toodumbtocode,这是一个不一致的地方,我希望他们能解决。请注意,在参数变量中,同样缺少初始化确实会导致'',就像在常规变量中一样;例如,& { param([string] $test1) $null -eq $test1 } 产生 $false。如果不一致性被删除并且您确实需要一个 $null 值 - 在 PowerShell 代码的上下文中这是不明智的 - 您必须使用 [NullString]::Value,如链接答案所示:class test { [string]$test1 = [NullString]::Value } $null -eq [test]::new().test1
        猜你喜欢
        • 1970-01-01
        • 2014-12-12
        • 1970-01-01
        • 1970-01-01
        • 2010-10-09
        • 1970-01-01
        • 2022-07-08
        • 1970-01-01
        • 2021-06-08
        相关资源
        最近更新 更多