How do I get a reference to a single dimension of a Multidemensional Array in C#?
I've come across a problem where I'd like to create an Array table. That is a 2 dimensional array where the number of rows and columns are known at runtime before the table needs to be created. The number of columns is the same for all rows.
Once the array is created I'd like to operate on just 1 dimension of that array. Perhaps pass a reference to an method.
Here is a fictional example:
// Create a table 3x3 table.
int[,] Distan开发者_如何学运维ceTable = new int[3, 3];
DistanceTable[0, 0] = 0;
DistanceTable[1, 1] = 0;
DistanceTable[2, 2] = 0;
DistanceTable[0, 1] = 10;
DistanceTable[0, 2] = 40;
DistanceTable[1, 0] = 10;
DistanceTable[1, 2] = 25;
DistanceTable[2, 0] = 40;
DistanceTable[2, 1] = 25;
// Why can't I do this?
int[] twos = DistanceTable[2];
If I were to use a JaggedArray (Array-of-Arrays) it lets me do this. But I don't need a JaggedArray because my multidemsional array always has the same number of columns for each row.
Is it possible to do this? If not why?
Thanks
No. Multidimensional arrays differ from Jagged arrays in that they are stored sequentially, in one block of memory, using Row-Major ordering.
Because of this, pulling out one "column" of data requires skipping in order to pull this out.
Jagged arrays, on the other hand, are an array of references to a second array. This makes it easy to pull out individual "arrays" from the jagged array.
But I don't need a JaggedArray because my multidemsional array always has the same number of columns for each row.
Jagged arrays in .NET have some huge performance optimizations. They often outperform multidimensional arrays. This is why most code analysis routines will suggest conversion to a jagged array from a two dimensional array. It would be worth considering this even if you don't "need" it.
This is not possible; multi-dimensional arrays do not work like that.
In general, you should always use jagged arrays; they're faster.
(The JITter will generate raw memory access instructions instead of method calls)
There is only one array object with a multidimensional array whereas a a jagged array is a nesting of multiple distinct array objects. There is not a 1-1 match-up or method of extraction (that does not involve using a wrapper).
I'm sorry, this should really be a comment to How do I get a reference to a single dimension of a Multidemensional Array in C#? but I'm not allowed to comment yet..
Anyway, the reason to why the performance is better with a jagged array is easy to understand after some explanation: Let's examine a multidimensional array:
{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}
In memory it's stored something like this: {0, 1, 2, 3, 4, 5, 6, 7, 8}.
Now, suppose you want to access [0, 0], where in memory are we going to read? We have to calculate the address: y * 3 + x => 0 * 3 + 0 => 0. After that, we can go on and do the actual read. In case we want to read the whole line, we have to do this math over and over again.
Instead, look at a jagged array, in memory it's stored something like this:
a: {0, 1, 2} b: {3, 4, 5} c: {6, 7, 8} {ref: a, ref:b, ref:c}
Suppose we want to access [0][0], where in memory are we going to read? First, let's get a reference to array [0]. And then get the content of cell [0]. Done. In case we want to read the whole line, we only need to increment the pointer by one.
If we are going to iterate through the whole "array" instead of just one row, it's still the same performance benefit for jagged arrays.
There's one exception though: iterate columns. That's really bad for jagged arrays since we are going to do a relative expensive memory-read for each and every access. Not good.
If you feel that it's a problem there's one method left: A one-dimensional array! In this case we use the theory behind the multidimensional array (y * rowLength + x), and use some really simple math; To iterate a row: just increment by one, to iterate a column: just increment by rowLength.
You could make an extension method on your DictionaryTable object that allows you to specify the row?
public static class IntArrayExt
{
public static int[] Row(this int[,] array, int row)
{
int[] newArray = new int[3];
for (int i = 0; i < array.Length; i++)
{
newArray[i] = array[row, i];
}
return newArray;
}
}
int[,] distanceTable = new int[3, 3];
distanceTable[0, 0] = 0;
distanceTable[1, 1] = 0;
distanceTable[2, 2] = 0;
distanceTable[0, 1] = 10;
distanceTable[0, 2] = 40;
distanceTable[1, 0] = 10;
distanceTable[1, 2] = 25;
distanceTable[2, 0] = 40;
distanceTable[2, 1] = 25;
int[] twos = distanceTable.Row(2);
You could make another extension method if you want to get a column.
精彩评论