使用 OutVariable 创建 ArrayList

Mar*_*tin 5 powershell

我确定发生这种情况是有正当理由的,但我不知道它是什么。我有以下代码

$Deleted = $Items[0].ParentNode.RemoveChild($Items[0])
Write-Output $Deleted
Run Code Online (Sandbox Code Playgroud)

如果我调用此代码使用

Do-Something -OutVariable Test
Run Code Online (Sandbox Code Playgroud)

我按预期在屏幕和变量中获得输出,但变量是一个ArraryList类型为单个元素的XmlElement

如果我跑

$Test = Do-Something
Run Code Online (Sandbox Code Playgroud)

我没有按预期在屏幕上得到输出,并且返回的输出是单个类型的对象 XmlElement

为什么OutVariable返回一个ArrayList而不是返回函数返回的单个项目?

谢谢

mkl*_*nt0 7

从 PowerShell [核心] 7.0 开始:

  • PowerShell的意外确实展开的命令的单个-object输出与
    -OutVariable
    :也就是说,即使命令仅输出一个对象,该对象被意外地存储为阵列中的目标变量,其名称被传递到公共参数(数组列表)-OutVariable参数(或其别名,-ov)。

  • 此外,该存储在目标变量中的值的类型总是[System.Collections.ArrayList],数组列表,这是不一致的与通过拍摄多对象输出在可变常规分配,这导致System.Object[],一个规则阵列

请参阅此 GitHub 问题

这是一个演示问题的简洁测试

$null = Get-Date -OutVariable ov; $ov.GetType().FullName
Run Code Online (Sandbox Code Playgroud)

从上面列出的版本开始,输出:

System.Collections.ArrayList
Run Code Online (Sandbox Code Playgroud)

即使输出是(在概念上)仅一个单个 [datetime][System.DateTime])实例。

将此与常规赋值进行对比:$v = Get-Date; $v.GetType().FullNameyields System.DateTime


解决方法是包装在子表达式运算符(输出变量参考$(...)),它给你的输出作为经由常规输出(成功)流相同的:

  • 单元素集合被解包(只输出元素本身)
  • 多元素集合作为System.Object[]数组返回。
# Note the $(...) around $ov
PS> $null = Get-Date -OutVariable ov; $($ov).GetType().FullName
System.DateTime  # 1-element System.Collections.ArrayList unwrapped
Run Code Online (Sandbox Code Playgroud)

当然,$ov[0]如果您只期望一个输出对象,您也可以使用。

该解决方法对多元素输出也有效的演示:

PS> $null = Get-ChildItem / -OutVariable ov; $($ov).GetType().FullName
System.Object[] # multi-element System.Collections.ArrayList converted to array
Run Code Online (Sandbox Code Playgroud)