powershell - 为管道重用自定义对象时出现意外结果

标签 powershell pipeline psobject new-object

不久前我改变了我的Join-Object cmdlet 似乎导致了一个错误,但在我的任何测试中都没有发现。
更改的目的主要是最小化代码并尝试通过准备自定义 PSObject 并在管道中重用它来提高性能。
作为Join-Object cmdlet 相当复杂,我创建了一个简化的 cmdlet 来显示具体问题:
(PowerShell版本为:5.1.16299.248)

Function Test($Count) {
    $PSObject = New-Object PSObject -Property @{Name = $Null; Value = $Null}
    For ($i = 1; $i -le $Count; $i++) {
        $PSObject.Name = "Name$i"; $PSObject.Value = $i
        $PSObject
    }
}

直接测试输出完全符合我的预期:

Test 3 | ft

Value Name
----- ----
    1 Name1
    2 Name2
    3 Name3

假设我是否将结果分配给变量(例如 $a)并不重要,但它确实如此:

$a = Test 3
$a | ft

Value Name
----- ----
    3 Name3
    3 Name3
    3 Name3

所以,除了分享这个经验之外,我想知道这是编程缺陷还是 PowerShell 错误/怪癖?

最佳答案

您原来的方法确实在概念上存在缺陷,因为您多次输出同一对象,迭代地修改其属性

输出差异由管道的逐项处理解释:

  • 输出到控制台(通过ft/Format-Table)打印当时> 每次迭代中 $PSObject 的状态,看起来一切都很好。

  • 相比之下,
  • 在变量中进行捕获反射(reflect)了所有迭代完成后$PSObject的状态,此时它仅包含最后迭代的值,Name33


您可以验证输出数组 $a 确实引用了同一个自定义对象三次,如下所示:

[object]::ReferenceEquals($a[0], $a[1]) # $True
[object]::ReferenceEquals($a[1], $a[2]) # $True

因此,解决方案是在每次迭代创建一个不同的[pscustomobject]实例:

PSv3+ 提供了用于创建自定义对象的语法糖:您可以将哈希表(文字)转换为 [pscustomobject]。由于这每次都会创建一个新实例,因此您可以使用它来简化您的功能:

Function Test($Count) {
  For ($i = 1; $i -le $Count; $i++) {
    [pscustomobject] @{ Name = "Name$i"; Value = $i  }
  }
}

这是您自己的PSv2 兼容解决方案:

Function Test($Count) {
    $Properties = @{}
    For ($i = 1; $i -le $Count; $i++) {
        $Properties.Name = "Name$i"; $Properties.Value = $i
        New-Object PSObject -Property $Properties
    }
}

关于powershell - 为管道重用自定义对象时出现意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49192685/

相关文章:

windows - Chocolatey 支持安装后命令吗?

powershell - Powershell脚本 block 变量范围和模块的奇怪行为,有什么建议吗?

amazon-web-services - 亚马逊网络服务数据管道

powershell - 如何通过 api 获取 Azure Devops/TFS 中特定构建中使用的变量

json - 从成功的 Invoke-RestMethod 中选择对象数据失败

powershell - 在 Powershell 中使用 ffmpeg

powershell - 在 Powershell 中映射驱动器的 "better"方式是什么?

continuous-integration - Gitlab CI 管道包含模板不起作用( secret 检测)

python - 如何访问管道中包含的模型中的最佳估计器参数?

vb.net - 如何在VB .NET中将包含 “”的字符串追加到现有字符串?