考虑以下示例:
$null
foreach ($n in $null) {'This is a $null test'}
(no output)
$null | ForEach-Object {'This is a $null test'}
This is a $null test
$null -in $null
True
$null -contains $null
True
[int]1
foreach ($n in [int]1) {'Test'}
Test
[int]1 | ForEach-Object {'Test'}
Test
[int]1 -in [int]1
True
[int]1 -contains [int]1
True
由于 $null 是一个不包含任何内容的标量值,因此在第二个 $null 示例中,$null 将沿着管道发送一个“nothing”的单个实例,这解释了输出。
为什么即使
$null
返回 $null -in $null
,也不能将 True
作为集合进行迭代?
tl;博士
您观察到的不对称性绝对是不幸的 - 但不太可能得到解决,以免破坏向后兼容性。
两者
<commandOrExpression> | ...
(管道)和foreach ($var in <commandOrExpression>) { ... }
如果
<commandOrExpression>
计算结果为 可枚举 的对象,则会自动枚举该对象,并且 枚举的元素将被一一处理。
本身处理;从某种意义上说:它被视为像单元素可枚举。
$null
null
,是一个特殊的something,恰好 代表“标量(单个)无”。
可枚举空形成对比 - 从技术上讲,[System.Management.Automation.Internal.AutomationNull]::Value
单例,又名“自动化空” - 这是当命令产生无输出时得到的结果。
$null
),并且枚举我会产生没有元素”。
foreach
循环和管道:
可枚举 null 作为输入,则 do 执行 no 枚举,因为它的目的是表明没有 没有可枚举的。
# Capture the output of a command that produces NO output.
$noOutput = Get-Item *NoSuchFile*
# No output, because the loop body is not executed.
foreach ($obj in $noOutput) { 'This does not print.' }
# Ditto.
$noOutput | ForEach-Object { 'This does not print' }
应该将$null
作为本身进行处理,因此会导致以
$null
作为要处理的(非)对象的单次迭代:
是它在管道中的工作方式,正如您问题中对ForEach-Object
$null
,正如您也观察到的那样。
:
输出的命令的输出分配给 variable 会隐式地将可枚举 null(表示缺少输出)转换为 $null
;在 v3+ 中(包括在
试图将输出存储在中间变量中相当于使用foreach
直接处理命令的输出,因此决定忽略$null
作为输入。例如,如果
$null
weren't
被
foreach
语句忽略,则以下命令的等效表述将not等效:
# DIRECT processing of command output.
foreach ($obj in Get-Item *NoSuchFile*) { 'This does not print' }
# INDIRECT processing of command output, via an intermediate variable.
$output = Get-Item *NoSuchFile*
# In v2, $output is now $null, not the enumerable null,
# and if $null were enumerated, the loop body would execute.
foreach ($obj in $output) { 'This does not print' }
pipeline,则不需要中间变量,在这种情况下不会出现问题。
但是,如果引用现有对象的不存在的属性,就会出现问题,因为它们的计算结果为$null
,因此导致$null
通过管道发送.
将对不存在的变量或属性的引用默认为
enumerable null$null
,这将隐式阻止管道和 foreach
语句中的枚举。
在expression 上下文中,可枚举 null 的行为类似于
$null
$null -eq $noSuchVariable
的内容将继续起作用。
foreach
$null
值,就像管道已经做的那样,这将消除不对称性。