You also have the option of omitting the sizes or providing just the sizes. These examples have them combined, which might be confusing as to why you see "[2][]". As an example, consider an array of int:
Code: int[] array1, array2, array3; // All are arrays of int
array1 = new int[] { 1,2,3 }; // No size needed, as it is clearly 3
array2 = new int[3]; // Allocate an array of 3 ints (no values assigned)
array3 = new int[3] { 1,2,3 }; // ...But you CAN do both
I think in the case of array2, the default value of 0 is given for each of the "3" ints in the new array. Now, let's replace "int" with "int[]", so that we have an array of int-arrays (and we can use the arrays from before as values in these arrays):
Code: int[][] a1, a2, a3, a4;
a1 = new int[][] { array1, array2, arra3 }; // each element is an int[]
a2 = new int[3][]; // Allocates a new array of 3 int[] values.
a3 = new int[3][] { array1, array2, array3 }; // as before.
a4 = new int[3][4]; // This is a shorthand for doing this:
// a4 = new int[][] { new int[4], new int[4], new int[4] };
One important thing to note is that array variables are stored as references (pointers). That is, when you create a "new" array, memory is allocated, and you get the ADDRESS of that array in memory, and that address is stored in the variable -- which is why the same int[] variable can point to a new int[3] and then later point to an int[5], etc. What this means for the "Array of arrays" example above is that you are storing an array of memory addresses for int arrays. They are called "jagged" because each "array in the array" might be a different size (because you are just storing their addresses). This also means that you can mix things up like so:
Code: int[][] arr = new int[][] {
array1, // This element in the array is the address of array1
new int[]{1,2}, // The element is the address of a new int array
new int[7], // ...So is this one
null // "no address" (represented internally as 0)
};
A "rectangular" array is like an array of arrays, except that the actual arrays are themselves are stored within an array, rather than just their addresses. For this, you provide all the dimensions (size) of the array in one place rather than giving each "inner" array its own size (hence "jagged"). These are more efficient if you want to store static data all in one place without having to go through references of references, etc. Example:
Code: int[,] rect1, rect2; // All are "rectangular" arrays of int
rect1 = new int[,] { // One new 3x6 "rectangle" of 18 ints
{ 0, 1, 2, 3, 4, 5},
{10,11,12,13,14,15},
{20,21,22,23,24,25}
};
rect2 = new int[6,7]; // A new 6x7 array (no values given)
rect2[3,3] = rect1[0,3]; // resulting value is 3
I belive you can combine them as well to have an array of rectangular arrays (int[][,]) or a rectangular array of arrays (int[,][]), etc. You can even add more dimensions, like a 3-dimensional array (int[,,]).