You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 04:05:22