Reputation: 5817
What I have found is that when I write the following function:
function test {
Write-Host ($input | Measure-Object).Count
Write-Host ($input | Measure-Object).Count
}
with sample input:
dir | test
it writes on the console:
18
0
I think it is because the first pipe to Measure-Object overwrites $input. I know of a workaround where I would make a new array and pass that around:
function test {
$inp = @($input)
Write-Host ($inp | Measure-Object).Count
Write-Host ($inp | Measure-Object).Count
}
However I don't like it because I am introducing a new variable. Is there a way of piping to a cmdlet while leaving $input unaffected?
Upvotes: 1
Views: 474
Reputation: 91835
$input
is an ArrayListEnumeratorSimple
:
C:\Users\roger> $input.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False True ArrayListEnumeratorSimple System.Object
...which means that it's an enumerator over a sequence of items. Thus, as you consume items in it, you use them up.
I attempted the following:
function foo
{
$input | select -first 3 | % { Write-Host -ForegroundColor 'Red' $_ }
$input | % { Write-Host -ForegroundColor 'White' $_ }
}
...to show that select -first 3
eats the first 3 items, but it appears to swallow all of them.
Trying the following:
function bar
{
$n = 0
foreach ($x in $input) {
if ( ++$n -eq 3 ) { break }
Write-Host -ForegroundColor 'Red' $x
}
$input | % { Write-Host -ForegroundColor 'White' $_ }
}
dir | bar
...shows the difference.
However, since $input is an enumerator (strictly an IEnumerator
), you can call Reset()
on it to rewind it.
Note that in .NET-land, not all enumerators can be reset. I'm not sure if there are any scenarios in PowerShell where this is the case with $input
.
Upvotes: 2
Reputation: 60918
Try this:
function test {
Write-Host ($input | Measure-Object).Count
$input.reset()
Write-Host ($input | Measure-Object).Count
}
reading about $input
enumerator
Upvotes: 2