Reputation: 1886
var board = Enumerable.Repeat(Enumerable.Repeat('.', 3).ToArray(), 3).ToArray();
board[0][0] = 'Q';
Here I'm trying to create array of arrays (3*3) populated with same element. But when I try to change one element ([0,0]) it changes first element of all three arrays. Why is that and how can this behavior be fixed without having 2 loops to initiate arrays?
Upvotes: 1
Views: 118
Reputation: 37060
Enumerable.Repeat()
returns the thing you give it. It doesn't create a new copy of it each time.
The inner Enumerable.Repeat()
returns the character '.' three times. Chars are a "value type", meaning that this creates a new copy of the character 'y':
char x = 'y';
You can't not create a copy of a value type when you assign it.
But arrays are a reference type, and the rules are different. The outer Enumerable.Repeat()
returns the same array object three times. You're not passing in an instruction to create a new array three times. You're passing in a reference to an existing array, and saying "give me that thing, three times". And unlike a character, giving you the same array again doesn't create a copy of it.
Arrays are a "reference type", meaning that the second line below creates a new reference to the same object:
char[] a = new [] { 'a', 'b', 'c' };
var y = a;
a
and y
are the same object. If you set a[0] = 'd';
, you can use the reference y
to look at that same array object, and you'll see the same letter 'd' in [0]
.
Enumerable.Repeat()
returns the same thing x number of times. It's not what you want if you're trying to create multiple instances of a value type.
This is what you want, if you want Linq:
var board = Enumerable.Range(0, 3)
.Select(n => Enumerable.Repeat('.', 3).ToArray())
.ToArray();
Select()
executes code each time, so the code you execute can create a new array each time. Repeat()
just keeps returning whatever value you gave it.
Upvotes: 1
Reputation: 24903
Because you created one array Enumerable.Repeat('.', 3).ToArray()
and cloned reference to this array 3 times.
So, you have 3 reference onto one value.
You need to initialize every row:
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';
Upvotes: 2