我试图理解@()数组构造函数的行为,我遇到了这个非常奇怪的测试。
似乎空管道的价值是"不完全"与$ null相同,即使它是-eq $ null
$x = 1,2,3,4 | ? { $_ -ge 3 }
$y = 1,2,3,4 | ? { $_ -ge 5 }
$z = $null
"x is $x"
"y is $y"
"z is $z"
if ($x -eq $null) {'x is null'} else {'x NOT null'}
if ($y -eq $null) {'y is null'} else {'y NOT null'}
if ($z -eq $null) {'z is null'} else {'z NOT null'}
$ax = @($x)
$ay = @($y)
$az = @($z)
"ax.length = " + $ax.length
"ay.length = " + $ay.length
"az.length = " + $az.length
"az[0].GetType "
$az[0].GetType()
产生以下输出
x is 3 4
y is
z is
x NOT null
y is null
z is null
ax.length = 2
ay.length = 0
az.length = 1
az[0].GetType
You cannot call a method on a null-valued expression.
At line:18 char:5
+ $az[0].GetType()
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
因此$ az数组的长度为1,$ az [0]为$ null。
但真正的问题是:$ y和$ z都可能都是-eq $ null,但是当我用@(...)构造数组时,一个数组是空的,另一个包含一个$ null元素?
答案 0 :(得分:6)
扩展Frode F.的回答,"没有"在PowerShell中是一个最神奇的值 - 它被称为[System.Management.Automation.Internal.AutomationNull] :: Value。以下内容的工作方式类似:
$y = 1,2,3,4 | ? { $_ -ge 5 }
$y = [System.Management.Automation.Internal.AutomationNull]::Value
PowerShell在大多数地方都将值AutomaticNull.Value视为$ null,但不是在任何地方。一个值得注意的例子是在一个管道中:
$null | % { 'saw $null' }
[System.Management.Automation.Internal.AutomationNull]::Value | % { 'saw AutomationNull.Value' }
这只会打印:
saw $null
请注意,即使您没有管道符,表达式本身也是管道,因此以下内容大致相同:
@($y)
@($y | Write-Output)
理解这一点,应该很清楚,如果$ y保存值AutomationNull.Value,则不会向管道写入任何内容,因此数组为空。
有人可能会问为什么$ null被写入管道。这是一个合理的问题。在某些情况下,脚本/ cmdlet需要指示"失败"没有使用例外 - 所以"没有结果"必须是不同的,$ null是用于这种情况的明显价值。
我从来没有遇到过一个人们需要知道你是否有价值"或$ null,但如果你这样做,你可以使用这样的东西:
function Test-IsAutomationNull
{
param(
[Parameter(ValueFromPipeline)]
$InputObject)
begin
{
if ($PSBoundParameters.ContainsKey('InputObject'))
{
throw "Test-IsAutomationNull only works with piped input"
}
$isAutomationNull = $true
}
process
{
$isAutomationNull = $false
}
end
{
return $isAutomationNull
}
}
dir nosuchfile* | Test-IsAutomationNull
$null | Test-IsAutomationNull
答案 1 :(得分:4)
您遇到此问题的原因是$null
是一个值。这是一个“没有价值”,但它仍然是一个价值。
PS P:\> $y = 1,2,3,4 | ? { $_ -ge 5 }
PS P:\> Get-Variable y | fl *
#No value survived the where-test, so y was never saved as a variable, just as a "reference"
Name : y
Description :
Value :
Visibility : Public
Module :
ModuleName :
Options : None
Attributes : {}
PS P:\> $z = $null
PS P:\> Get-Variable z | fl *
#Our $null variable is saved as a variable, with a $null value.
PSPath : Microsoft.PowerShell.Core\Variable::z
PSDrive : Variable
PSProvider : Microsoft.PowerShell.Core\Variable
PSIsContainer : False
Name : z
Description :
Value :
Visibility : Public
Module :
ModuleName :
Options : None
Attributes : {}
@()
的工作方式是,它保证结果在包装器(数组)中被传递。这意味着只要你有一个或多个对象,它就会将它包装在一个数组中(如果它不在像多个对象那样的数组中)。
$y
没什么,它是一个引用,但没有存储可变数据。所以没有什么可以创建一个数组。但是,$z
是一个存储变量,没有任何值(null-object)作为值。由于此对象存在,因此数组构造函数可以使用该项创建一个数组。