初始化阵列填充相同的元素
问题描述:
var board = Enumerable.Repeat(Enumerable.Repeat('.', 3).ToArray(), 3).ToArray();
board[0][0] = 'Q';
这里我试图创建数组(3 * 3)数组填充相同的元素。 但是,当我尝试更改一个元素([0,0])时,它会更改所有三个数组中的第一个元素。为什么会这样,以及如何修复这种行为,而无需2个循环来启动数组?初始化阵列填充相同的元素
答
Enumerable.Repeat()
返回你给它的东西。它不会每次都创建一个新的副本。
内部Enumerable.Repeat()
返回字符'。'三次。字符是“价值型”,也就是说这将创建字符“Y”的新副本:
char x = 'y';
当你将它不能不创造价值类型的副本。
但是数组是一个引用类型,并且规则是不同的。外部Enumerable.Repeat()
返回三次相同的数组对象。你没有通过三次创建新阵列的指令。你传递一个对现有数组的引用,并说“给我三次这样的事情”。而不像一个角色,再次给你相同的数组不会创建它的副本。
阵列是一个“引用类型”,也就是说,低于第二行创建一个新参考到相同对象:
char[] a = new [] { 'a', 'b', 'c' };
var y = a;
a
和y
是同一对象。如果您设置了a[0] = 'd';
,则可以使用参考y
来查看相同的数组对象,并在[0]
中看到相同的字母'd'。
Enumerable.Repeat()
x次返回相同的东西。如果你想创建一个值类型的多个实例,那不是你想要的。
这是你想要什么,如果你想的Linq:
var board = Enumerable.Range(0, 3)
.Select(n => Enumerable.Repeat('.', 3).ToArray())
.ToArray();
Select()
执行每次代码,所以你执行的代码每次可以创建一个新的数组。 Repeat()
只是不断返回你给它的任何价值。
答
因为你创建了一个数组Enumerable.Repeat('.', 3).ToArray()
并且克隆了这个数组的引用3次。 所以,你有3个参考到一个值。 需要初始化的每一行:
var board = Enumerable.Repeat((char[])null, 3).ToArray();
for (int i = 0; i < 3; i++)
{
board[i] = Enumerable.Repeat('.', 3).ToArray();
}
board[0][0] = 'Q';
是不是有一个原因,你没有宣布董事会作为一个数组从起点?也许如果你这样做,你可以声明你想要到达哪个数组。 –
@EthanTheBrave如果OP将它声明为'char [] [] board'并不重要,'var'处理它是一样的。 –