为什么用.Invoke()调用Powershell脚本块会返回一个集合?

时间:2012-01-27 03:57:20

标签: powershell powershell-v2.0 rationale

似乎调用Powershell脚本块(通过调用.Invoke()方法)总是生成一个集合。具体来说,是

类型的集合

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

即使调用空脚本块({}.Invoke())也会返回一个集合。使用调用运算符(&)调用相同的脚本块会产生正常预期的返回值(标量或[object[]])。

如果你需要一个集合而不是一个数组,这会很方便,但它似乎有点违反直觉。

有谁知道它为什么会这样?

编辑:

我知道有两种不同的调用,.Invoke().InvokeReturnAsIs()来自阅读语言规范。那是我第一次注意到它。

我只是不明白命名约定背后的原因以及它的机制似乎有效。查看文档,我认为默认的调用方法不是在Powershell中调用scriptblock时使用的方法。似乎.InvokeReturnAsIs()只返回一个对象流,然后如果有多个对象,则Powershell将其包装到一个对象数组中,如果只有一个对象则将​​其包装为标量,如果没有,则创建一个空对象,如如果那里有一个隐含的管道。使用.Invoke()始终返回一个集合,Powershell将其作为集合保留。

3 个答案:

答案 0 :(得分:10)

看起来是这两种方法之间的区别:

  

调用 - 使用指定的参数调用脚本块,   将结果作为PSObject对象返回。

     

InvokeReturnAsIs - 使用指定的参数运行脚本块。   此方法返回原始(未包装)结果对象,以便它可以   更有效率。

http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock_methods(v=vs.85).aspx

<强>调用

$code = {"a"}
$code.Invoke().Gettype().FullName

输出:

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]

<强> InvokeReturnAsIs

$code.InvokeReturnAsIs().GetType().FullName

输出:

System.String

答案 1 :(得分:5)

我的猜测是团队希望与PowerShell.Invoke() API保持一致,.NET Design Guidelines会返回Collection<PSObject>。这个C#签名使客户端更容易使用0,1或N个返回值,而不必担心检查null以及返回的对象是否被包装。

来自{{3}}:

  

不要从集合属性或方法返回空值   返回集合。返回一个空集合或一个空数组   代替。

你可以说,为什么不回归object。然后我将不得不反对null然后我必须测试它是否实现ICollection以确定我是否有标量或集合。从C#dev的角度来看,这是一个呕吐(原谅韵律)。 : - )

答案 2 :(得分:1)

因为这是它的设计目标,而且有另一种选择!

Invoke - 使用指定的参数调用脚本块,将结果作为PSObject对象的(集合)返回。

InvokeReturnAsIs - 使用指定的参数运行脚本块。此方法返回原始(未包装的)结果对象,以便更有效。

此外,{}.invoke()返回null,因此我不知道您在哪里获得的印象甚至会返回一个集合。

http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock.invokereturnasis(v=vs.85).aspx