Ответ 1
Результаты эмпирических испытаний
Я бы предпочел аналитическую основу для этих результатов, но мне нужен ответ, чтобы я мог двигаться дальше. Итак, вот результаты моего удара в эмпирическом тесте, чтобы узнать, какие коллекции разворачиваются конвейером 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
.
Вероятно, для некоторых типов существует некоторый нюанс. Этот нюанс можно проанализировать, посмотрев подробности выхода теста script ниже. Весь тест script ниже.
Тест Script
[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
Командлет
Это тестирование в конечном итоге привело меня к созданию командлета, который условно обертывает коллекции в жертвенные массивы (надеюсь) надежно предотвращает разворот цикла. Этот командлет называется Out-Collection
и находится в этом репозитории github.