Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Powershell : child object edit alters original parent object

I have a PowerShell multidimensional object called $foo.

If I want to edit one specific child object, I can use :

$foo[15].Name = 'Something'

But I want to edit that child object without editing the parent object.
If I use :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

$bar = $foo[15]
$bar.Name = 'Something'

This still edits the $foo parent object.

Why are $foo and $bar linked ?

Why, when I edit one, does it edit the other ?

Is there anyway to bypass this, so I can edit the subobject without altering the original, parent object ?

>Solution :

Why, when I edit one, does it edit the other ?

Because you’re dealing with a reference type, when you do:

$bar = $foo[15]

Then $foo[15] and $bar have the same reference, you can tell by using [object]::ReferenceEquals($objA, $objB), for example:

$foo = @(
    [pscustomobject]@{ Name = 'Something' }
    [pscustomobject]@{ Name = 'Something' }
)

$bar = $foo[1]
[object]::ReferenceEquals($foo[1], $bar) # True

Is there anyway to bypass this, so I can edit the sub object without altering the original, parent object ?

Yes there is and the method really depends on the type itself and its depth or complexity, for instance for these simple pscustomobjects provided above, they have only one level deep, for them specifically we could use the .Copy() method, this would produce a shallow copy of the object but in this case it would suffice:

$bar = $foo[1]
[object]::ReferenceEquals($foo[1], $bar) # True
$bar = $foo[1].PSObject.Copy()
[object]::ReferenceEquals($foo[1], $bar) # False

Now $bar can be safely updated without updating it’s original reference. Other reference types may provide their own cloning implementation, i.e. Hash tables have their own .Clone() Method. For more complex objects or objects with greater depth, the way around this is via serialization and deserialization, the 2 most commonly used methods in PowerShell are Json and CliXml:

$bar = $foo[1]
[object]::ReferenceEquals($foo[1], $bar) # True

# To and from Json
$bar = $foo[1] | ConvertTo-Json -Depth 99 | ConvertFrom-Json
[object]::ReferenceEquals($foo[1], $bar) # False

# To and from CliXml
$bar = [System.Management.Automation.PSSerializer]::Deserialize(
    [System.Management.Automation.PSSerializer]::Serialize($foo[1], 99))
[object]::ReferenceEquals($foo[1], $bar) # False
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading