在练习. GetType()方法时,我发现如果我编写一个返回“Name”和“BaseType”的函数,那么当我不编写该函数时,得到的结果与预期的结果不同。
示例:
function Get-BaseType_Name {
param(
[Parameter(Mandatory,ValuefromPipeline=$True)]
[System.Object]$var
)
$var.GetType() | Select -Property Name, BaseType;
}
$var = Get-Service
$var | Get-BaseType_Name
我得到:
Name BaseType
---- --------
ServiceController System.ComponentModel.Component
然而,如果我执行这些句子:
$var = Get-Service
$var.GetType() | Select -Property Name, BaseType;
我得到:
Name BaseType
---- --------
Object[] System.Array
为什么会这样?
我以为两种情况下会有相同的结果
2条答案
按热度按时间ut6juiuv1#
根据@MatthiasRJessen的回答,您是通过管道一次一个地将服务对象传递到函数中。
不过,还有一点--你只看到一个输出结果的原因是因为你的函数等价于:
也就是说,您的函数体被视为
end
块,如果查看PowerShell为您的代码生成的AST,您可以确认这一点:其产生以下输出。
(Note
BeginBlock
和ProcessBlock
为空,并且您的代码出现在EndBlock
中)。如果您看一下
about_Functions_Advanced_Methods
中的end
部分,它会说:结束
此块用于为函数提供可选的一次性后处理。
PowerShell将
Get-Service
的每个结果一次一个地输入到Get-BaseType_Name
函数中,但代码只有在处理完 last 项后才真正执行任何操作,在这种情况下,$var
保存了对最后一项的引用,如果运行以下代码,您可以看到这一点:在我的计算机上,我看到以下输出:
其中
XboxNetApiSvc
是Get-Service
返回的最后一个服务的名称。如果你想看到每个项的输出,你可以把你的代码放在
process
块中:然后你的optput看起来像这样
总之,您正在通过管道发送一个服务集合(根据@MathiasRJessen的回答),但您只返回了该集合中最后一个项的值,因为PowerShell隐式地将您的函数体视为
end
块...dgiusagp2#
从
about_Pipelines
帮助主题中:一次处理一个
[...]
当你通过管道将多个对象发送到命令时,PowerShell会将这些对象一次发送一个给命令。当你使用命令参数时,这些对象将作为单个数组对象发送。这个微小的差异会产生重大的影响。
执行管道时,PowerShell自动枚举实现
IEnumerable
接口的任何类型,并通过管道一次发送一个成员。[hashtable]除外,它需要调用GetEnumerator()方法。换句话说:这是设计使然- PowerShell发现
$var
包含一个数组(实现IEnumerable
接口的类型),并开始逐一枚举其中的项目您可以使用
Write-Output -NoEnumerate
来阻止自动枚举: