# 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
HashTables との不一致はかなりよく知られていますが、公式ドキュメントでは斜めにしか言及されていません (例を介して)。
ただし、関数の問題は私にとってニュースです。今まで噛まれたことがなかったのでちょっとショックです。スクリプターが従うことができる指針となる原則はありますか? C# でコマンドレットを記述する場合、明示的に列挙を制御できるWriteObject のオーバーロードがあることは知っていますが、知る限り、Posh 言語自体にはそのような構造はありません。最後の例が示すように、Posh インタープリターは、パイプされるオブジェクトのタイプに違いはないと考えているようです。内部で Object と PSObject の奇妙な点があるのではないかと思いますが、純粋な Posh を作成していて、スクリプト言語が「正常に機能する」ことを期待している場合、それはほとんど役に立ちません。
/ 編集 /
私の例では、3 つの文字列引数ではなく単一の string[] 引数を渡していることを Keith が指摘するのは正しいです。つまり、Measure-Object が Count=1 と言う理由は、最初の要素が @("a", "b", "c") である単一の配列の配列を参照しているためです。けっこうだ。この知識により、いくつかの方法で問題を回避できます。
# 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
しかし、それはすべてを説明していません...
# 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
私が推定できることから、別のルールが適用されます。要素が1つだけの配列があり、パーサーが式モードの場合、インタープリターはその要素を「ラップ解除」します。私が見逃している機微はありますか?