# array
C:\> (1,2,3).count
3
C:\> (1,2,3 | measure).count
3
# hashtable
C:\> @{1=1; 2=2; 3=3}.count
3
C:\> (@{1=1; 2=2; 3=3} | measure).count
1
# array returned from function
C:\> function UnrollMe { $args }
C:\> (UnrollMe a,b,c).count
3
C:\> (UnrollMe a,b,c | measure).count
1
C:\> (1,2,3).gettype() -eq (UnrollMe a,b,c).gettype()
True
Die Diskrepanz mit HashTables ist fairly well known, obwohl die official documentation es nur schräg erwähnt (über Beispiel).Was bestimmt, ob die Powershell-Pipeline eine Sammlung ausrollen soll?
Das Problem mit Funktionen ist jedoch neu für mich. Ich bin irgendwie geschockt, dass es mich jetzt nicht gebissen hat. Gibt es ein Leitprinzip, dem wir Skripter folgen können? Ich weiß, dass beim Schreiben von Cmdlets in C# overload of WriteObject, wo Sie die Aufzählung explizit steuern können, aber AFAIK gibt es kein solches Konstrukt in der Posh Sprache selbst. Wie das letzte Beispiel zeigt, scheint der Posh-Interpreter zu glauben, dass es keinen Unterschied in der Art der zu verrohrenden Objekte gibt. Ich vermute, dass es unter der Haube einige Object vs PSObject-Seltsamkeit gibt, aber das ist nutzlos, wenn Sie reines Posh schreiben und erwarten, dass die Skriptsprache "einfach funktioniert".
/EDIT/
Keith ist richtig darauf hinweisen, dass in meinem Beispiel, ich bin in einem einzigen String [] Argumente übergeben, anstatt 3 String-Argumente. Mit anderen Worten, der Grund, warum Measure-Object Count = 1 sagt, ist, weil es ein einzelnes Array-of-arrays sieht, dessen erstes Element @ ist ("a", "b", "c"). Meinetwegen. Dieses Wissen ermöglicht es Ihnen, in mehr Möglichkeiten, um das Problem zu umgehen:
# stick to single objects
C:\> (UnrollMe a b c | measure).count
3
# rewrite the function to handle nesting
C:\> function UnrollMe2 { $args[0] }
C:\> (UnrollMe2 a,b,c | measure).count
3
# ditto
C:\> function UnrollMe3 { $args | %{ $_ } }
C:\> (UnrollMe3 a,b,c | measure).count
3
Aber es erklärt nicht alles ...
# as seen earlier - if we're truly returning @(@("a","b","c")) why not count=1?
C:\> (UnrollMe a,b,c).count
3
# our theory must also explain these results:
C:\> ((UnrollMe a,b,c) | measure).count
3
C:\> (@(@("a","b","c")) | measure).count
3
C:\> ((UnrollMe a,b,c d) | measure).count
2
Von dem, was ich extrapolieren kann eine andere Regel im Spiel gibt es: wenn Sie haben ein Array mit genau einem Element UND der Parser ist in expression mode, dann wird der Interpreter das Element "auspacken". Noch mehr Feinheiten, die ich vermisse?
Das Äquivalent von WriteObject ist das Cmdlet Write-Output (aliased to echo), das nur selten verwendet wird, da Werte implizit an den Stdout-Stream ausgegeben werden. –
True, obwohl Write-Output keinen -EnumerateCollection-Parameter wie WriteObject (object, bool) hat. –
verwandt: http://stackoverflow.com/questions/28702588/in-what-conditions-does-powershell-unroll-items-in-the-pipeline/28707054#28707054 – alx9r