尝试编辑动态锯齿状数组中的单个元素会编辑多个元素

Trying to edit single elements in dynamic jagged array edits several instead

我正在尝试制作一个动态大小的锯齿状数组来表示一个非常简单的主机游戏的游戏网格。

# Determine the size of the board. Enforce the size so as to not make it too large. 
$boardSize = 5

# Game board characters
[char]$bushCharacter = "#"

# Initialize Game board object
$gameBoard = ,(@($bushCharacter) * $boardSize) * $boardSize

想法是,如果我要在屏幕上打印出来。我会得到这样的东西。

0..($boardSize - 1) | ForEach-Object{$gameBoard[$_] -join ""}

#####
#####
#####
#####
#####

一切都很好,直到我尝试对单个项目进行更改:$gameBoard[0][1] = "F"。我重印网格的预期结果是

#F###
#####
#####
#####
#####

我的实际输出是:

#F###
#F###
#F###
#F###
#F###

这告诉我,我创建的数组的所有行都相互引用。为什么此代码不创建单独的唯一数组?我可以做出什么改变来让它发挥作用。我知道其他方法会像使用 += 的索引循环一样工作,但我认为这种方法是更好的做法。

如果您查看乘法运算符 (*) 的文档,您会发现(来自 about_Arithmetic_Operators):

    *         Multiplies integers; copies strings     6*2
              and arrays the specified number of      "w" * 3
              times.

注意副本这个词。

现在查看 .NET Array.Copy() method 的 MSDN 文档,在 备注 部分下:

If sourceArray and destinationArray are both reference-type arrays or are both arrays of type Object, a shallow copy is performed. A shallow copy of an Array is a new Array containing references to the same elements as the original Array. The elements themselves or anything referenced by the elements are not copied. In contrast, a deep copy of an Array copies the elements and everything directly or indirectly referenced by the elements.

可以公平地假设数组乘法运算符 总是 产生相同类型的数组 - 即。引用类型数组或对象数组(无论是什么)——这基本上就是您所看到的效果。

我愿意:

$gameBoard = 1..$boardSize |ForEach-Object { ,@(@($bushCharacter) * $boardSize) }

Array 是一个 reference type,因此您只是乘以(复制)reference/pointer 而不是内容本身。

解决方法:创建循环以生成唯一数组。

$gameBoard = 0..($boardSize - 1) | ForEach-Object{ ,(@($bushCharacter) * $boardSize) }

您可以使用以下方法验证(无需文档)对象是引用类型:

Add-Type -AssemblyName "Microsoft.VisualBasic"
[Microsoft.VisualBasic.Information]::IsReference($gameBoard[0])
True

#or as mentioned by Mathias
-not $gameBoard[0].GetType().IsValueType
True