What are the differences between a multidimensiona

2018-12-31 01:08发布

What are the differences between multidimensional arrays double[,] and array-of-arrays double[][] in C#?

If there is a difference, what is the best use for each one?

9条回答
旧时光的记忆
2楼-- · 2018-12-31 01:39

I am parsing .il files generated by ildasm to build a database of assemnblies, classes, methods, and stored procedures for use doing a conversion. I came across the following, which broke my parsing.

.method private hidebysig instance uint32[0...,0...] 
        GenerateWorkingKey(uint8[] key,
                           bool forEncryption) cil managed

The book Expert .NET 2.0 IL Assembler, by Serge Lidin, Apress, published 2006, Chapter 8, Primitive Types and Signatures, pp. 149-150 explains.

<type>[] is termed a Vector of <type>,

<type>[<bounds> [<bounds>**] ] is termed an array of <type>

** means may be repeated, [ ] means optional.

Examples: Let <type> = int32.

1) int32[...,...] is a two-dimensional array of undefined lower bounds and sizes

2) int32[2...5] is a one-dimensional array of lower bound 2 and size 4.

3) int32[0...,0...] is a two-dimensional array of lower bounds 0 and undefined size.

Tom

查看更多
千与千寻千般痛.
3楼-- · 2018-12-31 01:41

Preface: This comment is intended to address the answer provided by okutane, but because of SO's silly reputation system, I can not post it where it belongs.

Your assertion that one is slower than the other because of the method calls isn't correct. One is slower than the other because of more complicated bounds-checking algorithms. You can easily verify this by looking, not at the IL, but at the compiled assembly. For example, on my 4.5 install, accessing an element (via pointer in edx) stored in a two-dimensional array pointed to by ecx with indexes stored in eax and edx looks like so:

sub eax,[ecx+10]
cmp eax,[ecx+08]
jae oops //jump to throw out of bounds exception
sub edx,[ecx+14]
cmp edx,[ecx+0C]
jae oops //jump to throw out of bounds exception
imul eax,[ecx+0C]
add eax,edx
lea edx,[ecx+eax*4+18]

Here, you can see that there's no overhead from method calls. The bounds checking is just very convoluted thanks to the possibility of non-zero indexes, which is a functionality not on offer with jagged arrays. If we remove the sub,cmp,and jmps for the non-zero cases, the code pretty much resolves to (x*y_max+y)*sizeof(ptr)+sizeof(array_header). This calculation is about as fast (one multiply could be replaced by a shift, since that's the whole reason we choose bytes to be sized as powers of two bits) as anything else for random access to an element.

Another complication is that there are plenty of cases where a modern compiler will optimize away the nested bounds-checking for element access while iterating over a single-dimension array. The result is code that basically just advances an index pointer over the contiguous memory of the array. Naive iteration over multi-dimensional arrays generally involves an extra layer of nested logic, so a compiler is less likely to optimize the operation. So, even though the bounds-checking overhead of accessing a single element amortizes out to constant runtime with respect to array dimensions and sizes, a simple test-case to measure the difference may take many times longer to execute.

查看更多
只靠听说
4楼-- · 2018-12-31 01:50

Multi-dimension arrays are (n-1)-dimension matrices.

So int[,] square = new int[2,2] is square matrix 2x2, int[,,] cube = new int [3,3,3] is a cube - square matrix 3x3. Proportionality is not required.

Jagged arrays are just array of arrays - an array where each cell contains an array.

So MDA are proportional, JD may be not! Each cell can contains an array of arbitrary length!

查看更多
登录 后发表回答