zdimension
zdimension

Reputation: 1082

Why are jagged arrays in C# defined in the opposite way?

Let's say I have a type called T. Now let's say I make an array of type T, it gives me T[]. In code, it gives:

var myArray = new T[10];

With a length of 10. So, we can see that this makes an array that contains 10 items of type T. This works if T is int, string, BinaryWriter or anything standard. But let's say T is an array type, like int[] or string[].

Then, if we want to define an array of 10 items of type T (int[]), it should give something like this:

var myArray = new int[][10];

By replacing T by int[] in the previous example. But this gives a syntax error, because the correct syntax in C# is:

var myArray = new int[10][];

Which, if we followed the logic of the first example, should give an array containing an undefined amount of arrays containing 10 integers.

The same applies for any dimension of jagged arrays:

var myArray = new int[][][10];

Is wrong because the syntactically correct way is:

var myArray = new int[10][][];

This isn't a personal preference or a code style debate, but simply logic: why is the syntax different when we define arrays of array types, than when we define arrays of anything else?

Upvotes: 6

Views: 464

Answers (2)

Nick
Nick

Reputation: 1038

This way, the initialization syntax mirrors the access syntax.

var myArray = new int[NUM_ROWS][];
...
/* Initialize rows of myArray */
...
var x = myArray[0][5]; /* Should this be row 0, col 5; or row 5, col 0? */

It would be counterintuitive for myArray[0][5] to be parsed as (myArray[5])[0] since the indices would be inverted left-to-right, so we instead have myArray[0][5] parsed as (myArray[0])[5].

As such, in myArray[i][j], i corresponds to the index into the two-dimensional array, and j corresponds to the index into the one-dimensional array myArray[i].

Now, i can range from 0 to NUM_ROWS-1, so it is symmetrical with the access syntax to initialize var myArray = new int[NUM_ROWS][]. This way, the left set of brackets still corresponds to the length of the two-dimensional array, and the right set of brackets still corresponds to the one-dimensional array.

Edit: I see someone posted in the comments a link to an article where Eric Lippert goes through a more elaborate example and justification.

Upvotes: 6

AaronLS
AaronLS

Reputation: 38374

new T[10] says you want an array of 10 items of type T. It is not the same as new int[][10] because it does not behave like a preprocessor macro in other languages. It doesn't just swap T with whatever the type is to create new int[][10]. Instead it is being consistent with the fact that T is always the inner type and new T[10] defines the size of the outer array.

So if T was DateTime then you'd expect to have 10 date times and access them such as myArray[9].Day

If each item T is an int[] then you'd still always index into the array of 10 items and then access the item T, which is an array: myarray[9][2465] assuming the inner array at index 9 had at least 2466 items.

So the index of the outer array always comes first.

A T[10] is a size 10 array of items T. Whatever T is the inner item.

You state your expectation is that new T[10] would produce var myArray = new int[][10];. However even in C++ when declaring a multidimensional array, the outer dimension comes first in the declaration:

https://www.tutorialspoint.com/cplusplus/cpp_multi_dimensional_arrays.htm

Declaring a jagged array is similar in C++ except you must use pointer syntax and first declare the outer array then initialize each inner array separately.

Let's think about it in terms of the semantics of what each statement is saying:

A) new T[10]: I want an array of outer dimension 10, with each element containing a type T

B) new T[10] where T is int[]: I want an array of outer dimension 10, with each element containing an int array of unknown length.

C) new int[][10]: I want an array of outer dimension unknown, with each element containing an array of 10 integers.

D) new int[10][]: I want an array of outer dimension 10, with each element containing an int array of unknown length.

Notice that B and D match, but B and C do not match.

Upvotes: 1

Related Questions