给出以下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
循环?
答案 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