PowerShell 5自定义类存入哈希表后更新异常问题求助
问题描述
我创建了一个PowerShell自定义类变量,并将其存入哈希表的键值对“value”部分。但当我更新该自定义类中的整数字段时,另一个键值对也随之改变。
程序代码
class Contact { [ValidateNotNullOrEmpty()][string]$First [ValidateNotNullOrEmpty()][string]$Last [ValidateNotNullOrEmpty()][int]$Changes } $ClassMates=@{} $C = [Contact]@{ First = "Joel" Last = "Bennett" Changes = 0 } $ClassMates['Child1']=$C $C.First="Justine" $C.Last="Smith" $C.Changes=0 $ClassMates['Child2']=$C write-host "All Class Mates" write-host "---------------" foreach ($child in $ClassMates.Keys) { Write-Host $child ":" [Contact] $thischild=$($ClassMates.Item($child)) write-host $thischild.First write-host $thischild.Last write-host $thischild.Changes } $C=$ClassMates['Child2'] $C.First="Justine" $C.Last="Smythe" $C.Changes++ $ClassMates['Child2']=$C write-host "All Class Mates After Update" write-host "----------------------------" foreach ($child in $ClassMates.Keys) { Write-Host $child ":" [Contact] $thischild=$($ClassMates.Item($child)) write-host $thischild.First write-host $thischild.Last write-host $thischild.Changes }
运行输出
.\CustomVarTypes2.ps1 All Class Mates --------------- Child1 : Justine Smith 0 Child2 : Justine Smith 0 All Class Mates After Update ---------------------------- Child2 : Justine Smythe 1 Child1 : Justine Smythe 1
可以看到Child1的Changes字段本应保持为0,请问哪里出错了?该如何修复?
问题原因
PowerShell中的自定义类属于引用类型,当你把$C对象存入哈希表时,哈希表中存储的并不是对象的副本,而是指向该对象在内存中的引用地址。所以Child1和Child2两个键实际上指向的是同一个Contact对象,无论修改哪一个引用指向的对象属性,都会影响到所有指向该对象的键值对。
修复方法
需要为每个哈希表条目创建独立的Contact实例,避免复用同一个对象引用。有两种常见方式:
方式1:每次添加时创建新实例
不用复用$C变量,每次添加到哈希表前都新建一个Contact对象:
$ClassMates=@{} # 添加Child1 $ClassMates['Child1'] = [Contact]@{ First = "Joel" Last = "Bennett" Changes = 0 } # 添加Child2,创建新实例 $ClassMates['Child2'] = [Contact]@{ First = "Justine" Last = "Smith" Changes = 0 } # 后续更新Child2时,修改的是独立实例 $C = $ClassMates['Child2'] $C.Last = "Smythe" $C.Changes++ $ClassMates['Child2'] = $C
方式2:复制现有对象的属性到新实例
如果需要基于现有对象创建新实例,可以复制原对象的属性到新的Contact实例中:
$ClassMates=@{} $C = [Contact]@{ First = "Joel" Last = "Bennett" Changes = 0 } $ClassMates['Child1'] = $C # 复制$C的属性到新实例,再存入Child2 $ClassMates['Child2'] = [Contact]@{ First = $C.First Last = $C.Last Changes = $C.Changes } # 修改Child2的属性 $ClassMates['Child2'].First = "Justine" $ClassMates['Child2'].Last = "Smith" # 后续更新操作只会影响Child2的独立实例 $C = $ClassMates['Child2'] $C.Last = "Smythe" $C.Changes++ $ClassMates['Child2'] = $C
内容的提问来源于stack exchange,提问作者phillip-from-oz
相关产品推荐
相关产品推荐

