Under what conditions does powershell expand items in the pipeline?

Consider the following:

function OutputArray{ $l = @(,(10,20)) $l } (OutputArray) -is [collections.ienumerable] # C:\ PS> True (OutputArray).Count # C:\ PS> 2 

$l "unfolds" when it enters the pipeline . This answer says powershell expands all collections . A hash table is a collection . However, the hash table, of course, is independent of the pipeline:

 function OutputHashtable{ $h = @{nested=@{prop1=10;prop2=20}} $h } (OutputHashtable) -is [collections.ienumerable] # C:\ PS> True (OutputHashtable).Count # C:\ PS> 1 

This comment assumes that all IEnumerable are converted to arrays of objects . However, both the array and the ienumerable hash table:

 @(,(10,20)) -is [collections.ienumerable] #True @{nested=@{prop1=10;prop2=20}} -is [collections.ienumerable] #True 

What exactly are the conditions when powershell "deploys" objects into the pipeline?

+13
collections powershell ienumerable pipeline
Feb 24 '15 at 17:38
source share
1 answer

Empirical Test Results

I would prefer an analytical framework for these results, but I need an answer so that I can move on. So, here are the results of my hit in an empirical test to find out which collections are deployed by the powershell pipeline and which are not:

True in the column indicates that some rollout is likely to occur.

 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 

These are the results for a powershell line that looks like this:

 $result = $starting | Cmdlet 

^ The ChangedInCmdlet column indicates that the $starting type is different when it appears inside the Cmdlet .

** The ChangedWhenEmitted column indicates that the type of $result is different when it is assigned $ result, when it was emitted inside the Cmdlet .

There is probably some nuance for some types. This nuance can be analyzed by looking at the details of the test script output below. The whole test script is below.

Script test

 [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

This testing ultimately led me to create a cmdlet that conditionally wraps collections in sacrificial arrays (I hope) reliably prevents the loop from turning around. This cmdlet is called Out-Collection and is located in this github repository .

+10
Feb 24 '15 at 21:51
source share



All Articles