PowerShell is great in many ways yet very unintuitive in others.
Consider following example:
$a = 0 $b = $a $b = 1 $a #0 $b #1
All seems good and logical? Now introduce arrays:
$a=@(1) $a #1 $b=$a $b[0]=2 $a #2! $b #2
What? How did $a change? Surely this is an artifact of direct modification or something. Let’s try passing array to a function.
$a=@(1) function b {param($c);$d=$c;$d[0]=2;$d} $a #1 b $a #2 $a #2!
Now that’s annoying if you’re passing the same array around in a script. No level of scoping or any other tinkering will fix that. A bit of MSDN and StackOverflow reveals that arrays are always, and I mean always, passed by reference, something inherited from .Net. There are a few not-so-pretty workarounds.
use .Clone() method. Caveat is that it only works one level. So it you use multidimensional arrays, you’re out of luck. Example:
$a=@(1,@(1)) function b {param($c);$d=$c.Clone();$d[0]=2;$d[1][0]=2;$d} $a #1,1 b $a #2,2 $a #1,2!
As you can see, first level of array works fine but second does not.
Serialize-deserialize array. That’s a really ugly workaround but it’s guaranteed to work. Take a look here. I haven’t tested it because cloning worked for my needs but I have a feeling that it is much slower. That may or not be an issue depending on your requirements. Might be a good idea to wrap it in a function for easy use.
Wishlist: runtime flag or global variable to pass arrays by value.