首页 > 解决方案 > Powershell - 为每个对象调用函数时的奇怪行为会更改所有对象中的数组

问题描述

我遇到了一些我无法解决的奇怪问题,所以希望有人能对此有所了解。不知道为什么,但是我对函数中对象的数组所做的任何事情都会影响/改变其他对象数组。

这就是我所做的。我描述对象类:

Class testObject {
   [array] $list
   [int] $increment }

然后我创建两个具有相同 $list 的对象:

$numberList = (1,1,1,1,1,1,1,1,1)

$obj1 = New-Object testObject
$obj1.list = $numberList
$obj1.increment = 2

$obj2 = New-Object testObject
$obj2.list = $numberList
$obj2.increment = 5

接下来,我将描述将每个数组项增加每个对象中指定的增量值的函数:

Function Increase-numbers ($obj) {
    [array] $array = $obj.list

    For ($i = 0; $i -lt 9; ++$i) {
        $array[$i] += $obj.increment }

    $obj.list = $array
    return $obj
}

然后我运行将对象传递给函数的函数,并使用函数结果更新对象:

$obj1 = Increase-numbers $obj1
Write-Host "$($obj1.list)"

$obj2 = Increase-numbers $obj2
Write-Host "$($obj2.list)"

我希望返回的值是: 对于 $obj1(增量值 = 2):333333333 对于 $obj2(增量值 = 5):666666666

但它实际上返回:333333333 888888888

发生这种情况是因为在我更改数组值的第一个函数调用中,它也会自动更新 $obj2 数组值。

有谁知道我做错了什么?

标签: arrayspowershellobject

解决方案


编辑:正如下面提到的@mklement0,最有可能的做法是:

# other code here
$obj1.list = $numberList.Clone() # Instead of $numberList.PsObject.Copy()
# other code here
$obj2.list = $numberList.Clone() # Instead of $numberList.PsObject.Copy()
# other code here

这是提供的解释:

我建议使用 $numberList.Clone(),不仅因为它比有点晦涩难懂的 .psobject.Copy() 更简单,而且因为后者可能给人一种错误的印象,即它是一种通用的对象克隆机制,而事实并非如此。 t - 任何不是 [pscustomobject] 或实现 ICloneable 的引用类型的实例都将按原样返回 - 换句话说:调用实际上是一个安静的无操作。例如,它适用于可散列({ ... }),但不适用于有序品种([ordered] @{ ... })



原答案:

发生这种情况是因为您是$numberList按引用复制,而不是按值复制。一旦您增加了第一个值,Increase-numbers它就会为引用该列表的所有变量增加它。

如果你改变:

# other code here
$obj1.list = (1,1,1,1,1,1,1,1,1)
# other code here
$obj2.list = (1,1,1,1,1,1,1,1,1)
# other code here

对此:

# other code here
$obj1.list = $numberList.PsObject.Copy()
# other code here
$obj2.list = $numberList.PsObject.Copy()
# other code here

它应该对您有用,因为您正在复制$numberList按值,到$obj1.list- 按值复制将其视为一个全新的变量。您也可以执行以下操作:

# other code here
$obj1.list = (1,1,1,1,1,1,1,1,1)
# other code here
$obj2.list = (1,1,1,1,1,1,1,1,1)
# other code here

或者..

$numberList1 = (1,1,1,1,1,1,1,1,1)
$numberList2 = $numberList1.PsObject.Copy()
# other code here
$obj1.list = $numberList1
# other code here
$obj2.list = $numberList2
# other code here

或者..

$numberList1 = (1,1,1,1,1,1,1,1,1)
$numberList2 = (1,1,1,1,1,1,1,1,1)
# other code here
$obj1.list = $numberList1
# other code here
$obj2.list = $numberList2
# other code here

推荐阅读