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

mjo*_*nor 6 powershell powershell-2.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())也会返回一个集合.使用call运算符(&)调用相同的脚本块会产生正常预期的返回(标量或[object[]]).

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

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

编辑:

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

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

And*_*ndi 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
Run Code Online (Sandbox Code Playgroud)

输出:

System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]
Run Code Online (Sandbox Code Playgroud)

InvokeReturnAsIs

$code.InvokeReturnAsIs().GetType().FullName
Run Code Online (Sandbox Code Playgroud)

输出:

System.String
Run Code Online (Sandbox Code Playgroud)


Kei*_*ill 5

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

.NET设计指南:

不要从集合属性或返回集合的方法返回空值.返回一个空集合或一个空数组.

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