在处理集合的任何命令或类似于
ForEach-Object
的命令中,直接使用
-InputObject
作为参数是没有意义的,因为该命令被设计为处理集合,需要将其展开并逐个处理元素。但我也不会称这个参数为“无用”,因为它仍然需要被定义,以便可以设置允许通过管道输入。
为什么是这样呢?
-InputObject
是约定俗成的一个通用参数名称,应该被视为管道输入。它是一个具有[Parameter(ValueFromPipeline = $true)]
设置的参数,因此更适合从管道获取输入而不是作为直接参数传递。将其作为直接参数传递的主要缺点是,不能保证集合被展开,可能会出现一些未预期的行为。来自上面链接到的about_pipelines
页面的说明:
当您将多个对象通过管道传递给命令时,PowerShell会逐个向命令发送对象。当您使用命令参数时,对象会被发送为单个数组对象。这个微小的差别具有重大的影响。
为了用不同的话解释上面的引用,通过管道传递集合(例如,一个数组或列表)将自动展开该集合并将其逐个传递到管道中的下一个命令中。该命令不会展开-InputObject
本身,数据是逐个元素传递的。这就是为什么将集合直接传递给-InputObject
参数可能会出现问题的原因 - 因为该命令可能没有设计来展开集合,它期望每个集合元素都以逐个分开的方式交给它。
请考虑以下示例:
$myHash = @{name = 'Alex'}, @{name='Bob'}, @{name = 'Sarah'}
$myHash | Where-Object { $_.name -match 'alex' }
以上代码按预期输出以下内容:
Name Value
---- -----
name Alex
但是如果你直接像这样将哈希作为
InputArgument
传递:
Where-Object -InputObject $myHash { $_.name -match 'alex' }
它返回整个集合,因为通过管道传递时
-InputObject
从未展开,但在此上下文中,
$_.name -match 'alex'
仍然返回true。换句话说,当将集合直接作为参数提供给
-InputObject
时,
它被视为单个对象而不是针对集合中的每个元素执行每次操作。这也可以在检查该数据集的错误条件时呈现出预期工作的
外观:
Where-Object -InputObject $myHash { $_.name -match 'frodo' }
在这种情况下,返回的是空值,因为即使在这种情况下,frodo
也不是哈希集合中任何一个name
键的值。
简而言之,如果某个东西期望输入作为管道输入传递,通常情况下,尤其是传递集合时,以这种方式进行操作更加安全。然而,如果您正在使用非集合项目,则使用-InputObject
参数直接传入也可能没有问题。