Powershell: массив PSCustomObject как параметр в функции неожиданно изменяется - PullRequest
2 голосов
/ 30 марта 2020

В приведенном ниже упрощенном коде PS я не понимаю, почему массив $MyPeople изменяется после вызова функции changeData. Эта переменная массива должна быть просто скопирована, и я ожидаю, что функция вернет другую переменную массива в $UpdatedPeople и не коснется $MyPeople:

function changeData {
    Param ([PSCustomObject[]]$people)
    $changed_people = $people
    $changed_people[0].Name = "NEW NAME"
    return $changed_people
}
# Original data:
$Person1 = [PSCustomObject]@{
    Name    = "First Person"
    ID      = 1
}
$Person2 = [PSCustomObject]@{
    Name    = "Second Person"
    ID      = 2
}
$MyPeople = $Person1,$Person2

"`$MyPeople[0] =`t`t" + $MyPeople[0]
"`n# Updating data..."
$UpdatedPeople  = changeData($MyPeople)
"`$UpdatedPeople[0] =`t" + $UpdatedPeople[0]
"`$MyPeople[0] =`t`t" + $MyPeople[0]

Вывод на консоль:

$MyPeople[0] =          @{Name=First Person; ID=1}
# Updating data...
$UpdatedPeople[0] =     @{Name=NEW NAME; ID=1}
$MyPeople[0] =          @{Name=NEW NAME; ID=1}

Спасибо!

Ответы [ 2 ]

2 голосов
/ 30 марта 2020

PSObject2 = PSObject1 не копия, а ссылка. Вам необходимо клонировать или скопировать исходный объект, используя метод, разработанный для этой цели.

function changeData {
    Param ([PSCustomObject[]]$people)
    $changed_people = $people | Foreach-Object {$_.PSObject.Copy()}
    $changed_people[0].Name = "NEW NAME"
    return $changed_people
}

Методика выше упрощена c и должна работать здесь. Однако это не глубокий клон. Поэтому, если ваши свойства psobject содержат другие psobjects, вам нужно изучить глубокий клон.

1 голос
/ 30 марта 2020

Мы можем клонировать объект PSCustomObject. Мы создадим новый PSObject и перечислим его через psobject, заданный в качестве параметра, и добавим их одного за другим в мелкую копию.

function changeData {
    Param ([PSCustomObject[]]$people)
    $changed_people = New-Object PSobject -Property @{}
    $people.psobject.properties | ForEach {
      $changed_people | Add-Member -MemberType $_.MemberType -Name $_.Name -Value $_.Value
    }
    $changed_people[0].Name = 'NEW NAME'
    return $changed_people
}

Или воспользуемся другим методом @ AdminOfThings

...