为什么可以循环通过空数组

时间:2014-02-13 13:36:05

标签: powershell

给出以下PowerShell代码:

$FolderItems = Get-ChildItem -Path "C:\Test"

Write-Host "FolderItems Is Null: $($FolderItems -eq $null)"

foreach ($FolderItem in $FolderItems)
{
    Write-Host "Inside the loop: $($FolderItem.Name)"
}

Write-Host "Done."

当我使用C:\Test文件夹中的一个文件对其进行测试时,会输出:

FolderItems Is Null: False
Inside the loop: MyFile.txt
Done.

但是,当我使用文件夹中的ZERO文件对其进行测试时,会输出:

FolderItems Is Null: True
Inside the loop: 
Done."

如果$FolderItems为空,那么为什么它会进入foreach循环?

3 个答案:

答案 0 :(得分:4)

这是在V1中进行的有意设计选择,并在V3中重新进行。

在大多数语言中,foreach语句只能循环遍历事物集合。 PowerShell总是有点不同,在V1中,除了值集合之外,您还可以遍历单个值。

例如:

foreach ($i in 42) { $i }  # prints 42

在V1中,如果值是一个集合,foreach将迭代集合中的每个元素,否则它将进入该循环以获得该值。

在上面的句子中注意,$ null并不特殊。这只是另一个价值。从语言设计的角度来看,这是相当简洁和简洁的解释。

不幸的是,许多人并没有预料到这种行为会导致许多错误。我认为会出现一些混淆,因为人们期望foreach语句的行为几乎与foreach-object cmdlet一样。换句话说,我认为人们期望以下方面的工作方式相同:

$null | foreach { $_ }
foreach ($i in $null) { $i }

在V3中,我们认为改变行为非常重要,因为我们可以帮助脚本编写者避免在脚本中引入错误。

请注意,改变行为理论上可能会以意想不到的方式破坏现有脚本。我们最终决定在foreach语句中可能看到$ null的大多数脚本已经使用if来保护foreach语句,例如:

if ($null -ne $c)
{
    foreach ($i in $c) { ... }
}

所以实际上,大多数现实世界的脚本都不会看到行为的变化。

答案 1 :(得分:0)

这是V1和V2中ForEach的特质/错误。它已在V3版本中得到纠正。

答案 2 :(得分:-1)

在我看来,您需要将foreach包裹在检查$FolderItem != null的条件中。这样,只要if$FolderItems,就永远不会进入NULL语句

If (-NOT $FolderItems -eq $null) {
    foreach ($FolderItem in $FolderItems)
    {
        Write-Host "Inside the loop: $($FolderItem.Name)"
    }
}

这也可能有所帮助http://bit.ly/1brKRRk