# 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 , где вы можете явно управлять перечислением, но AFAIK нет такой конструкции в самом языке Posh. Как показывает последний пример, интерпретатор Posh, похоже, считает, что нет никакой разницы в типе объектов, передаваемых по конвейеру. Я подозреваю, что может быть некоторая странность Object против PSObject под капотом, но это бесполезно, когда вы пишете чистый Posh и ожидаете, что язык сценариев «просто сработает».
/ РЕДАКТИРОВАТЬ /
Кит правильно указал, что в моем примере я передаю один строковый аргумент, а не 3 строковых аргумента. Другими словами, причина, по которой 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
Из того, что я могу экстраполировать, есть еще одно правило в игре: если у вас есть массив с ровно одним элементом И парсер находится в режиме выражения , то интерпретатор "развернет" указанный элемент. Есть еще какие-то тонкости, которые мне не хватает?