初始化填充了相同元素

时间:2017-05-25 13:01:15

标签: c# arrays

var board = Enumerable.Repeat(Enumerable.Repeat('.', 3).ToArray(), 3).ToArray();
board[0][0] = 'Q';

这里我试图创建填充相同元素的数组(3 * 3)。 但是当我尝试更改一个元素([0,0])时,它会更改所有三个数组的第一个元素。为什么这样,如果没有2个循环来启动数组,如何解决这个问题呢?

2 个答案:

答案 0 :(得分:2)

因为你创建了一个数组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';

答案 1 :(得分:1)

Enumerable.Repeat()会返回您提供的内容。它不会每次都创建它的新副本。

内部Enumerable.Repeat()会返回字符&#39;。&#39;三次。字符是&#34;值类型&#34;,这意味着这会创建字符的新副本&#39; y&#39;:

char x = 'y';

分配时,您无法 创建值类型的副本。

但是数组是引用类型,规则是不同的。外Enumerable.Repeat()返回相同的数组对象三次。您没有传递三次创建新阵列的指令。你传递了对现有数组的引用,然后说&#34;给我那个东西,三次&#34;。与角色不同,再次为您提供相同的阵列并不会创建它的副本。

数组是&#34;引用类型&#34;,这意味着下面的第二行为同一个对象创建了一个新的引用

char[] a = new [] { 'a', 'b', 'c' };
var y = a;

ay 是同一个对象。如果您设置了a[0] = 'd';,则可以使用引用y查看同一个数组对象,并且您将看到相同的字母&#39; d&#39;在[0]

Enumerable.Repeat()返回相同的内容x次。如果您尝试创建值类型的多个实例,那么这不是您想要的。

这就是你想要的,如果你想要Linq:

var board = Enumerable.Range(0, 3)
            .Select(n => Enumerable.Repeat('.', 3).ToArray())
            .ToArray();
每次

Select() 执行代码,因此您执行的代码每次都可以创建一个新数组。 Repeat()只是不断返回你给它的任何价值。