5

I am using PowerShell 2.0. When I make a new variable as an array and then set another variable to be equal to the first one, the second variable "mirrors" the first one. After changing an object in the original array, the exact same change appears in the second array. For instance,

$array0001 = 6, 7, 3, 4, 0
$array0002 = $array0001
$array0001[3] = 55
$array0002

with the output being

6
7
3
55
0

I notice that when you set the second variable to have the same value as the first variable, except this time enclosed within a subexpression operator, modifications to the first array do not affect the second array. For instance,

$array0001 = 6, 7, 3, 4, 0
$array0002 = $($array0001)
$array0001[3] = 55
$array0002

with the output being

6
7
3
4
0

Why does enclosing the value in a subexpression operator change the behavior of the variable? Is there another or better way to avoid making array variables that "mirror" each other?

ETA: I have now found that $array0002 = @($array0001) and $array0002 = &{$array0001} both accomplish the exact same objective.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sine62677
  • 53
  • 5

2 Answers2

7

It's called "pass by reference". Instead of actually assigning a value, you're assigning a reference to another location that holds a value. If the value in the original location changes, the reference you made is pointing to that original location, and will see the updated value.

Most languages have ways to "pass by reference" and "pass by value". That's what you found by doing $array0002=$($array0001). Neither one is better than the other, they just both have different uses.

In PowerShell you can also put .value behind your reference to grab the value, instead of the reference.

coinbird
  • 1,202
  • 4
  • 24
  • 44
2

When setting one array equal to another like that, the different variables are simply referencing eachother, it's not a true copy. This is essentially the same thing that you are asking. From that link, serializing the data to do a deep copy is a good way around it.

#Original data
$Array1 

# Serialize and Deserialize data using BinaryFormatter
$ms = New-Object System.IO.MemoryStream
$bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$bf.Serialize($ms, $Array1)
$ms.Position = 0

#Deep copied data
$Array2 = $bf.Deserialize($ms)
$ms.Close()
Nick
  • 1,178
  • 3
  • 24
  • 36