views:

106

answers:

2

I have a simple question:

Why the program below does not write the whole array $lines? It is looping forever. I am really confused..

function Get-Current ($enumerator) {
    $line = $enumerator.Current
    return $line
}

$lines = @('a', 'b', 'c')
$enumerator = $lines.GetEnumerator()
$enumerator.Reset()

while ($enumerator.MoveNext()) {
    $line = Get-Current $enumerator
    "$line"     
}
A: 

Don't know why MoveNext never returns false. This works

$lines = @('a', 'b', 'c')
$enumerator = $lines.GetEnumerator()

while ($enumerator.MoveNext()) {
    $enumerator.Current
}
Doug Finke
Ok, I know. I would never used those statements to simply iterate an array. The snippet is just an illustration.So my question still is why the function call "damage" the enumerator.
Marek Pavluch
@Marek Tried to rename the parameter, tried to wrap in PsObject but nothing worked. Pretty tricky behaviour :)
stej
+2  A: 

It seems as though the expression:

$enumerator

unwinds the entire enumerator. For e.g.:

PS C:\> $lines = @('a', 'b', 'c')
PS C:\> $enumerator = $lines.GetEnumerator()
PS C:\> $enumerator.Reset()
PS C:\> $enumerator
a
b
c

So, when you try to pass your expression to the function, it is rendered invalid. The only workaround I can think of is to pass it as a PSObject like so:

function Get-Current ($val) {
    $val.Value.Current
}

$lines = @('a', 'b', 'c')
$enumerator = $lines.GetEnumerator()
$enumerator.Reset()

while ($enumerator.MoveNext()) {
    $line = Get-Current $(get-variable -name enumerator)
    $line
}
zdan
@zdan: That is exactly what I have meant! Thank you.
Marek Pavluch
PowerShell automatically unwraps arrays and enumerators in many cases. This is usually pretty handy and time saving, but sometimes it causes problems as you can see.
JasonMArcher