为什么空的 Powershell 散列 table 会在空数组的计算结果为 False 时计算为 True?

Why does an empty Powershell hash table evaluate to True when an empty array evaluates to False?

我正在 Powershell 4.0 中试验 True 和 False。以下是查看空数组和空哈希 table:

时的结果
PS C:\Users\simon> $a = @()    
PS C:\Users\simon> if ($a) { Write-Host "True" } else { Write-Host "False" }
False

PS C:\Users\simon> $a = @{}    
PS C:\Users\simon> if ($a) { Write-Host "True" } else { Write-Host "False" }
True

为什么当空数组的计算结果为 False 时空散列 tables 的计算结果为 True?

根据 Powershell 文档 About Comparison Operators

When the input is a collection of values, the comparison operators return any matching values. If there are no matches in a collection, comparison operators do not return anything.

因此我希望散列 table 和数组在它们为空时表现相同,因为它们都是集合。我希望两者都评估为 False,因为它们 return 与 if 子句无关。

这不是 True/False 的问题。您可以使用布尔运算符 $true$false 对此进行测试。我使用 $h 作为空哈希表 @{}

PS C:\> $a = @()
PS C:\> $h = @{}
PS C:\> if ($a -eq $true) { Write-Host "True" } else { Write-Host "False" }
False

if ($h -eq $true)    >  False
if ($a -eq $false)   >  False
if ($h -eq $false)   >  False

也不等于自动变量$null:

if($a -eq $null)     >  False
if($h -eq $null)     >  False

根据, Count is a better test to see if a hashtable/array is empty.

不同的行为将与基本类型相关。

PS C:\> $a.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

PS C:\> $h.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Hashtable                                System.Object

这与if语句和Length属性、AFAICS语句的工作方式有关。以下是我(诚然不稳定)从多篇 Whosebug 帖子和外部链接中得到的理解。


Get-Member 行为不同 - 请参阅 Mathias's explanation

$a | Get-Member            # Error - Get-Member : You must specify an object for the Get-Member cmdlet.
$h | Get-Member            # TypeName: System.Collections.Hashtable. Has Count method, no Length property
Get-Member -InputObject $a # TypeName: System.Object[]. Has Count method, has Length property

变量的Length属性不一样。但是哈希表没有 Length 属性 - .

$a.Length   > 0
$h.length   > 1

结合 Ansgar's link 解释了 if 语句中的不同行为,因为它似乎隐含地获得了 Length 属性 。它还允许我们这样做:

if ($a.Length -eq $true)    >  False
if ($h.Length -eq $true)    >  True

使用 [String] .Net class 的 IsNullOrEmpty method 给出与 $null 不同的输出,我假设是因为这也依赖于 Length

if ([string]::IsNullOrEmpty($a))    > True
if ([string]::IsNullOrEmpty($h))    > False