【问题标题】:Why does invoking a Powershell script block with .Invoke() return a collection?为什么使用 .Invoke() 调用 Powershell 脚本块会返回一个集合?
【发布时间】:2012-02-20 04:15:08
【问题描述】:

似乎调用 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 中调用脚本块时使用的方法。似乎.InvokeReturnAsIs() 只是返回一个对象流,然后如果有多个对象,Powershell 会将其包装到一个对象数组中,如果只有一个对象则为标量,如果没有则创建一个空对象,就好像有那里有一个隐式管道。使用.Invoke() 总是返回一个集合,而Powershell 将其保留为一个集合。

【问题讨论】:

    标签: powershell powershell-2.0 rationale


    【解决方案1】:

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

    Invoke - 使用指定参数调用脚本块, 将结果作为 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
    

    【讨论】:

      【解决方案2】:

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

      来自.NET Design Guidelines

      不要从集合属性或方法返回空值 返回收藏。返回一个空集合或一个空数组 而是。

      那你可以说为什么不直接返回object。然后我将不得不反对null,然后我必须测试它是否实现了ICollection,以确定我是否有一个标量或集合。从 C# 开发人员的角度来看,这是一个喷子(请原谅押韵)。 :-)

      【讨论】:

        【解决方案3】:

        因为这就是它的设计目的,而且还有一个替代方案!

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

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

        另外,{}.invoke() 返回 null,所以我不知道您从哪里得到即使返回集合的印象。

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

        【讨论】:

        • 当我这样做时,我想到了它作为集合的想法:({}.invoke).gettype()
        • Get-Member -InputObject ({}.invoke()) 表明它也返回一个集合;相反,$null -eq {}.Invoke() 返回$False。返回的集合是 empty,这就是它在控制台中不产生输出的原因。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-06
        • 1970-01-01
        • 2015-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多