Переданный объект не обновляется при вызове вложенной функции

#powershell

#powershell

Вопрос:

Я создаю новый объект (1) с некоторыми свойствами. Я передаю этот объект функции (1), которая затем вызывает другую функцию (2). Функция (2) сама создает объект (2) того же типа и возвращает его с Write-Output . Затем обратно в функцию (1) объекту (1) присваивается возвращаемое значение. Поскольку объекты передаются по ссылке, я бы ожидал, что объект (1) будет обновлен за пределами области действия функции. Но это не так.

Основной сценарий:

 $RootFolder = "C:xyz"

. "$RootFolderFunctionFile - Copy.ps1"
. "$RootFolderFile - Copy.ps1"

$Object_Test = [PSCustomObject]::new()
$Object_Test | Add-Member -MemberType NoteProperty -Name "a" -Value 0
$Object_Test | Add-Member -MemberType NoteProperty -Name "b" -Value 0

Write-Host "Before function call: $Object_Test"
Initialize-ObjectMutation -Object $Object_Test
Write-Host "After function call: $Object_Test"
  

Функция(1) (‘File — Copy.ps1’):

 function Initialize-ObjectMutation {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)] [PSCustomObject]$Object
    )

    Write-Host "Before function call (inside): $Object"
    $Object = New-Object
    Write-Host "After function call (inside): $Object"
}
  

Функция(2) (‘FunctionFile — Copy.ps1’):

 function New-Object {
    $Object = [PSCustomObject]::new()
    $Object | Add-Member -MemberType NoteProperty -Name "a" -Value 1
    $Object | Add-Member -MemberType NoteProperty -Name "b" -Value 1

    Write-Output $Object
}
  

Вывод:

 Before function call: @{a=0; b=0}
Before function call (inside): @{a=0; b=0}
After function call (inside): @{a=1; b=1}
After function call: @{a=0; b=0}
  

Не могли бы вы сказать мне, что я делаю не так, или какую концепцию я здесь неправильно понял? Пожалуйста, также не стесняйтесь давать советы о том, как я мог бы решить это лучшим способом.
В реальной жизни функция (1) сделала бы еще кое-что и с другой рукой, полной переменных. На самом деле это оболочка для функций, подобных function(2).

Комментарии:

1. Не вызывайте [PSCustomObject]::new() внутри функции. Вместо этого просто обновите переданный объект.

2. Большое спасибо! Это работает. Отметил бы это как ответ, поскольку в моих глазах он выглядит более гладким, чем ответ от Хассана. Можете ли вы, пожалуйста, объяснить, почему он не работал так, как я это делал?

Ответ №1:

Это один из способов заставить его работать, используя мой собственный $ RootFolder. Объект передается по ссылке, а значения копируются из возвращающей функции.

main.ps1

 $RootFolder = "H:Codingstack"

. "$RootFolderFunctionFile - Copy.ps1"
. "$RootFolderFile - Copy.ps1"

$Object_Test = [PSCustomObject]::new()
$Object_Test | Add-Member -MemberType NoteProperty -Name "a" -Value 0
$Object_Test | Add-Member -MemberType NoteProperty -Name "b" -Value 0

Write-Host "Before function call: $Object_Test"
Initialize-ObjectMutation -Object ([ref]$Object_Test)
Write-Host "After function call: $Object_Test"
  

File — Copy.ps1

 function Initialize-ObjectMutation {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)][ref]$Object
    )

    Write-Host "Before function call (inside): $($Object.value)"
    
    $return = New-Object

    $Object.value.a = $return.a;
    $Object.value.b = $return.b;

    Write-Host "After function call (inside): $($Object.value)"
}
  

FunctionFile — Copy.ps1

 function New-Object {
    $Object = [PSCustomObject]::new()
    $Object | Add-Member -MemberType NoteProperty -Name "a" -Value 1
    $Object | Add-Member -MemberType NoteProperty -Name "b" -Value 1

    return $Object
}
  

Результаты

 PS H:Codingstack> ./main.ps1
Before function call: @{a=0; b=0}
Before function call (inside): @{a=0; b=0}
After function call (inside): @{a=1; b=1}
After function call: @{a=1; b=1}
  

Комментарии:

1. Привет, Хассан, большое спасибо, это работает! Но я действительно надеялся, что смогу избежать этого [ref] … Может кто-нибудь объяснить, почему объект не был передан по ссылке в первой строке? Это работает, если в функции ‘New-Object’ не создан новый объект. Это потому, что $Object становится ссылкой на «новый объект» из New-Object?

2. Эй, это также работает, если я делаю это в ‘File — Copy.ps1’: $Object_New = New-Object; $Object.a = $Object_New.a; $Object.b = $Object_New.b .