问题描述
PS 中的 function 使用起来非常自由,但它会对返回值做一种奇怪的处理。
我们一起来看下面这段代码,你认为这个 function 的返回值是什么类型?
function TestReturn () { $ls = [System.Collections.Generic.List[int]]::new() $ls.Add(1) return $ls } $(TestReturn).GetType()
喂!这怎么看都是返回了一个 List<int> 吧?
但是你运行之后得到的结果是这样的:

啊!!!我 List<int> 呢???
然后当我们“天真地”将这个返回值当作一个 List<int> 使用时,大概会得到一个:
“Method invocation failed because [System.Int32] does not contain a method named 'xxx'.”
原因分析
不止 List<int> 会这样, Queue<int> 以及其他常用的泛型/非泛型集合、甚至 Array 都是副德性……那我们大概可以进一步推测:所有 collection 都是这德性(欢迎读者验证并评论)。
具体原因不明,大概只有 PS 的设计者能解释了吧。
我推测与它对于多个返回值的处理有关(http://www.pstips.net/powershell-specify-return-value-from-function.html),这个设计的逻辑感觉就像是:
“多个返回值变成一个 Object[],只包含一个 item 的 collection 返回值会变成一个 item”
前者显然是有好处的,但我看不到后者的意义,希望知情者能在评论区解释一下,感激不尽!
解决方案
我还是希望得到一个 collection(返回的类型与 collection 的 Count 相关什么的真是太扯了)。
所以对于这种多此一举的设计,我选择使用 PS 强大的类型转换(http://www.pstips.net/powershells-type-conversion-magic.html)解决:每当调用的函数可能返回一个仅包含一项的 collection 时,通过强制类型转换得到预期的 collection 类型。
$tr = [System.Collections.Generic.List[int]]$(TestReturn)
当然,你也可以选择 Foreach-Object 这样强大的 cmdlet,这样就不必纠结它是 item 还是 collection 了,也许这样更符合 PS 设计者的初衷?