如何向List动态添加PSCustomObject并避免元素值同步变更?
问题根本原因
[PSCustomObject] 是引用类型,你在循环外仅创建了1个对象实例,后续所有添加到List的都是同一个对象的内存引用。修改这个实例的属性时,所有指向该内存地址的引用都会同步生效,因此最终所有元素的属性值都是最后一次修改的结果。
修复方案
1. 基础循环场景(对应示例代码)
每次循环迭代时创建新的PSCustomObject实例即可,实例创建的性能开销极低,完全适配超大文件解析场景:
$list = [System.Collections.Generic.List[object]]::new() foreach ($i in 1..5) { # 每次循环创建新的独立实例 $item = [PSCustomObject]@{ count = $i } $list.Add($item) }
执行$list | Format-Table即可得到count值从1到5的预期输出。
2. 适配并行解析+按行号更新的场景
你提到的$list.$field[$lineNumber] = <字段值>更新方式存在语法错误,正确写法为$list[$lineNumber].$field = <字段值>,同时需要提前为List初始化对应行数的独立空对象,避免多个行指向同一个实例:
# 提前获取CSV总行数赋值给$totalLines $totalLines = 10000 $list = [System.Collections.Generic.List[object]]::new() # 预初始化所有行的独立PSCustomObject实例 for ($lineNum = 0; $lineNum -lt $totalLines; $lineNum++) { $list.Add([PSCustomObject]@{ # 提前声明所有需要用到的CSV字段,初始值设为$null即可 Field1 = $null Field2 = $null # 其他字段按需补充 }) }
预初始化完成后,运行空间池的并行逻辑中修改对应行的属性时,只会修改当前行的独立实例,不会影响其他行。
3. 性能与线程安全说明
[System.Collections.Generic.List]的读写性能远高于+=重建数组,完全满足超大CSV解析需求,每次新建PSCustomObject的开销可忽略不计。- 多线程场景下如果仅修改已有位置的对象属性(不新增/删除List元素),不需要额外加锁;如果需要动态添加元素,建议改用线程安全的
[System.Collections.Concurrent.ConcurrentBag[object]]类型避免多线程写入冲突,该类型兼容PowerShell 5.1版本。
内容的提问来源于stack exchange,提问作者Blaisem
相关产品推荐
相关产品推荐

