Ric*_*erg 9 collections powershell ienumerable pipeline
# 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
Run Code Online (Sandbox Code Playgroud)
与HashTables的差异是众所周知的,尽管官方文档仅提到它(通过示例).
但是,功能问题对我来说是个新闻.我有点震惊,现在还没有咬过我.我们编程人员可以遵循一些指导原则吗?我知道在C#中编写cmdlet时会出现WriteObject的重载,您可以在其中明确地控制枚举,但是AFAIK在Posh语言本身中没有这样的构造.正如最后一个例子所示,Posh解释器似乎相信被管道对象的类型没有区别.我怀疑在引擎盖下可能会有一些Object vs 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
Run Code Online (Sandbox Code Playgroud)
但是,它并不能解释一切......
# 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
Run Code Online (Sandbox Code Playgroud)
根据我可以推断的另一个规则:如果你有一个只有一个元素的数组并且解析器处于表达式模式,那么解释器将"解包"所述元素.我错过了更多的微妙之处?
Kei*_*ill 11
$ args已展开.请记住,函数参数通常使用空格来分隔它们.当您传入1,2,3时,您传入的是一个由三个数组组成的数组,该数组被赋值给$ args [0]:
PS> function UnrollMe { $args }
PS> UnrollMe 1 2 3 | measure
Count : 3
Run Code Online (Sandbox Code Playgroud)
将结果(数组)放在分组表达式(或子表达式$()
)中使其再次符合展开条件,因此以下展开包含UnrollMe返回的1,2,3的对象[]:
PS> ((UnrollMe 1,2,3) | measure).Count
3
Run Code Online (Sandbox Code Playgroud)
这相当于:
PS> ((1,2,3) | measure).Count
3
Run Code Online (Sandbox Code Playgroud)
顺便说一句,它不仅适用于具有一个元素的数组.
PS> ((1,2),3) | %{$_.GetType().Name}
Object[]
Int32
Run Code Online (Sandbox Code Playgroud)
@()
在已经是数组的东西上使用数组子表达式()无论你应用它多少次都没有效果.:-)如果你想阻止展开使用逗号运算符,因为它将始终创建另一个展开的外部数组.请注意,在这种情况下,您并没有真正阻止展开,您只需通过引入一个外部"包装"数组来展开展开,而不是原始数组,例如:
PS> (,(1,2,3) | measure).Count
1
Run Code Online (Sandbox Code Playgroud)
最后,执行此操作时:
PS> (UnrollMe a,b,c d) | %{$_.GetType().Name}
Object[]
String
Run Code Online (Sandbox Code Playgroud)
您可以看到UnrollMe将两个项目(a,b,c)作为数组返回,d作为标量返回.这两个项目分别从管道发送,结果计数为2.
归档时间: |
|
查看次数: |
2874 次 |
最近记录: |