2

在 Mac 上使用 PowerShell Core 6.1。似乎将数组传递给 ForEach-Object 正在修改或包装每个元素,以便 -is 运算符将所有元素视为 PSCustomObjects。

让我演示一下:

设置一个由四个不同类型的项目组成的数组(使用 JSON,因为这是我真实用例中数据的来源):

$a = '[4, "Hi", {}, true]' | ConvertFrom-Json

按索引迭代列表并确定哪些是 PSCustomObjects:

0..3 | ForEach-Object { 
    $v = $a[$_]
    $t = $v.GetType().FullName
    $is = $v -is [PSCustomObject]
    "$t - $is"
}

输出(对我来说)正是我所期望的:

System.Int64 - False
System.String - False
System.Management.Automation.PSCustomObject - True
System.Boolean - False

但是,如果我只是将数组传递给 ForEach-Object:

$a | ForEach-Object { 
    $v = $_
    $t = $v.GetType().FullName
    $is = $v -is [PSCustomObject]
    "$t - $is"
}

现在输出声称所有四个都是 PSCustomObjects:

System.Int64 - True
System.String - True
System.Management.Automation.PSCustomObject - True
System.Boolean - True

谁能解释这里发生了什么?

4

1 回答 1

1

PetSerAl就像他经常做的那样,在评论中提供了关键的指针:

管道对象ForEach-Object将它们包装在一个实例中(如/[psobject]中所反映的那样),这导致/返回任何输入对象$_$PSItem-is [pscustomobject]-is [psobject]$True,因为 - 令人困惑 -[pscustomobject][psobject]它们都是类型加速器[System.Management.Automation.PSObject]- 与预期相反[pscustomobject]不是的缩写。[System.Management.Automation.PSCustomObject]

因此,测试输入对象是不是的[System.Management.Automation.PSCustomObject]实例[pscustomobject]

$a | ForEach-Object {
  $_ -is [System.Management.Automation.PSCustomObject]
}

请注意,如果您使用foreach 循环,甚至-is [pscustomobject]可以工作,因为被枚举的对象不会被包装在额外的[psobject]实例中:

foreach ($element in $a) {
  $element -is [pscustomobject]
}

这是可行的,因为即使是善意的[System.Management.Automation.PSCustomObject],在技术上也是[System.Management.Automation.PSObject]幕后的。

于 2018-11-13T04:45:13.717 回答