Using the *
operator on non-numeric values creates copies of the original value. However, if the item you're copying isn't of a primitive(-ish) type like String or Char, the result will not be a duplicate of that object, but a copy of the object reference. Since all instances will then be pointing to the same object, changing one will change all.
To create distinct instances you need to repeat the array instantiation in a loop, as PetSerAl showed in the comments:
$arr = 1..3 | ForEach-Object { ,(,'E' * 3) }
In this particular case you could also create a "template" array and clone it:
$a0 = ,'E' * 3
$arr = 1..3 | ForEach-Object { ,$a0.Clone() }
Note, however, that cloning an object will not clone nested object references, so the latter is not a viable approach in all scenarios.
Something like this won't work the way you intend (because the references of the nested hashtable objects are still pointing to the same actual hashtables after cloning the array object):
PS C:\> $a0 = ([PSCustomObject]@{'x'='E'}),([PSCustomObject]@{'x'='E'})
PS C:\> $arr = 1..2 | ForEach-Object { ,$a0.Clone() }
PS C:\> $arr
x
-
E
E
E
E
PS C:\> $arr[1][1].x = 'F'
PS C:\> $arr
x
-
E
F
E
F
But something like this will work:
PS C:\> $arr = 1..2 | ForEach-Object { ,(([PSCustomObject]@{'x'='E'}),([PSCustomObject]@{'x'='E'})) }
PS C:\> $arr
x
-
E
E
E
E
PS C:\> $arr[1][1].x = 'F'
PS C:\> $arr
x
-
E
E
E
F