PowerShell接收函数返回ArrayList时意外混入索引数值的输出异常
PowerShell 函数返回ArrayList时前置索引值的问题定位与修复
问题根因
这个异常不存在随机逻辑错误,是两个机制叠加导致的固定可复现行为:
- 首先,.NET中
[System.Collections.ArrayList]的Add()方法自带int类型返回值,返回值就是新添加元素在列表中的索引位置:列表加第1个元素返回0,加第2个返回1,依次累加。 - 其次,PowerShell的函数返回逻辑和C#等传统语言有本质区别:函数内所有没有被显式接收、没有被丢弃的管道输出,都会被统一收集为函数的最终返回值。哪怕你在函数末尾写了
return $arrayToReturn,也不会清除之前已经漏到管道里的输出内容。
看示例代码的执行流程:
- 调用
$arrayToReturn.Add('logICM_20210222_075234315.txt')时,方法返回的索引值0没有被任何变量接住,直接流入函数的输出管道。 - 后续
return $arrayToReturn时,会把之前管道里的0,和当前要返回的ArrayList打包成一个集合,赋值给外部的$fileNames。 - 执行
Write-Host $fileNames时,PowerShell会自动展开集合里的所有内容:先是管道里的int值0,再枚举ArrayList里的字符串元素,最终输出就变成了0 logICM_20210222_075234315.txt。
如果是包含4个元素的场景,每次Add()调用返回的0、1、2、3四个索引值全部漏到管道中,打印时自然会出现依次前置索引值、再拼接所有数组元素的现象,和观察到的表现完全匹配。
修复方式
只需要在调用Add()时,显式丢弃它的返回值,不让内容进入管道即可,常见实现有三种等价写法:
- 用
[void]前缀强制丢弃返回值:function returnAnArray{ $arrayToReturn =[System.Collections.ArrayList]::new() [void]$arrayToReturn.Add('logICM_20210222_075234315.txt') return $arrayToReturn } - 用空变量接收返回值:
$null = $arrayToReturn.Add('logICM_20210222_075234315.txt') - 管道传递给Out-Null丢弃输出:
$arrayToReturn.Add('logICM_20210222_075234315.txt') | Out-Null
内容的提问来源于stack exchange,提问作者Raymond Arcand
相关产品推荐
相关产品推荐

