powershell - powershell 在什么情况下会在管道中展开项目?

标签 powershell collections ienumerable pipeline

考虑以下:

function OutputArray{
    $l = @(,(10,20))
    $l
}

(OutputArray) -is [collections.ienumerable]
# C:\ PS> True
(OutputArray).Count
# C:\ PS> 2
$l is "unrolled" when it enters the pipeline . This answer states that powershell unrolls all collections . A hashtable is a collection .但是,哈希表当然不受管道的影响:
function OutputHashtable{
    $h = @{nested=@{prop1=10;prop2=20}}
    $h
}

(OutputHashtable) -is [collections.ienumerable]
# C:\ PS> True
(OutputHashtable).Count
# C:\ PS> 1

This comment suggests that it is all IEnumerable that are converted to object arrays .但是,数组和哈希表都是可枚举的:
@(,(10,20)) -is [collections.ienumerable]
#True
@{nested=@{prop1=10;prop2=20}} -is [collections.ienumerable]
#True

Powershell 将对象“展开”到管道中的确切条件是什么?

最佳答案

实证检验结果
我宁愿对这些结果有一个分析基础,但我需要一个答案,这样我才能继续前进。因此,以下是我进行实证测试的结果,以发现哪些集合被 powershell 的管道展开,哪些不是:
列中的 True 表示可能发生了一些展开。

StartingType                          ChangedInCmdlet^  ChangedWhenEmitted**
------------                          ---------------   ------------------
System.String                                           
System.Collections.ArrayList          True              True
System.Collections.BitArray           True              True
System.Collections.Hashtable
System.Collections.Queue              True              True
System.Collections.SortedList
System.Collections.Stack              True              True
System.Collections.Generic.Dictionary                   
System.Collections.Generic.List       True              True
这些是一行 powershell 的结果,如下所示:
$result = $starting | Cmdlet
^ ChangedInCmdlet列表示$starting的类型当它出现在 Cmdlet 里面时是不同的.
** ChangedWhenEmitted列表示$result的类型分配给 $result 时与在 Cmdlet 中发出时不同.
对于某些类型,可能存在一些细微差别。可以通过查看下面测试脚本输出的详细信息来分析这种细微差别。整个测试脚本如下。
测试脚本
[System.Reflection.Assembly]::LoadWithPartialName('System.Collections') | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName('System.Collections.Generic') | Out-Null

Function BackThroughPipeline{
    [CmdletBinding()]
    param([parameter(position=1)]$InputObject)
    process{$InputObject}
}

Function EmitTypeName{
    [CmdletBinding()]
    param([parameter(ValueFromPipeline=$true)]$InputObject)
    process{$InputObject.GetType().FullName}
}

$objects = (New-Object string 'TenTwentyThirty'),
           ([System.Collections.ArrayList]@(10,20,30)),
           (New-Object System.Collections.BitArray 16),
           ([System.Collections.Hashtable]@{ten=10;twenty=20;thirty=30}),
           ([System.Collections.Queue]@(10,20,30)),
           ([System.Collections.SortedList]@{ten=10;twenty=20;thirty=30}),
           ([System.Collections.Stack]@(10,20,30)),
           (& {
               $d = New-Object "System.Collections.Generic.Dictionary``2[System.String,int32]"
               ('ten',10),('twenty',20),('thirty',30) | % {$d.Add($_[0],$_[1])}
               $d
           }),
           (& {
               $l = New-Object "System.Collections.Generic.List``1[int32]"
               10,20,30 | % {$l.Add($_)}
               $l
           })

$objects | 
    % {
        New-Object PSObject -Property @{
                StartingType  = $_.GetType().FullName
                StartingCount = $_.Count
                StartingItems = $_
                InCmdletType  = $_ | EmitTypeName
                InCmdletCount = ($_ | EmitTypeName).Count
                AfterCmdletType   = (BackThroughPipeline $_).GetType().FullName
                AfterCmdletItems  = (BackThroughPipeline $_)
                AfterCmdletCount  = (BackThroughPipeline $_).Count
                ChangedInCmdlet    = if ($_.GetType().FullName -ne ($_ | EmitTypeName) ) {$true};
                ChangedWhenEmitted = if (($_ | EmitTypeName) -ne (BackThroughPipeline $_).GetType().Fullname ) {$true}
            }
    }
Out-Collection Cmdlet
这个测试最终让我创建了一个 cmdlet,它有条件地将集合包装在牺牲数组中,以(希望)可靠地防止循环展开。该 cmdlet 名为 Out-Collection并且在 this github repository .

关于powershell - powershell 在什么情况下会在管道中展开项目?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28702588/

相关文章:

c++ - 在命令提示符和 PowerShell 中运行 C++ 程序的区别

Powershell模拟键盘

Azure Powershell : Find the creator of a virtual machine

c# - 在 OrderBy 中维护子序列顺序

powershell - 从多个扩展属性中选择一个属性

javascript - 使用 Promise 处理 firestore 任务

python - 在 Python 中,如何确定可迭代对象是否具有稳定的迭代顺序?

java - 覆盖哈希码方法时的HashMap性能

c# - Where() 的 IEnumerable lambda 表达式