[英]What determines whether the Powershell pipeline will unroll a collection?
[英]In what conditions does powershell unroll items in the pipeline?
考慮以下:
function OutputArray{
$l = @(,(10,20))
$l
}
(OutputArray) -is [collections.ienumerable]
# C:\ PS> True
(OutputArray).Count
# C:\ PS> 2
$l
進入管道時“展開” 。 這個答案表明powershell展開了所有集合 。 哈希表是一個集合 。 但是,哈希表當然不受管道的影響:
function OutputHashtable{
$h = @{nested=@{prop1=10;prop2=20}}
$h
}
(OutputHashtable) -is [collections.ienumerable]
# C:\ PS> True
(OutputHashtable).Count
# C:\ PS> 1
這條評論表明,所有IEnumerable都轉換為對象數組 。 但是,數組和散列表都是不可數的:
@(,(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
列表示當它出現在Cmdlet
時, $starting
的類型是不同的。
** ChangedWhenEmitted
列指示$result
的類型在從Cmdlet
內部發出時分配給$ result時是不同的。
對於某些類型,可能存在一些細微差別。 可以通過查看下面測試腳本輸出的詳細信息來分析這種細微差別。 整個測試腳本如下。
[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
,位於此github存儲庫中 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.