Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的多维数组和数组数组之间有什么区别?_C#_Multidimensional Array_Jagged Arrays - Fatal编程技术网

C#中的多维数组和数组数组之间有什么区别?

C#中的多维数组和数组数组之间有什么区别?,c#,multidimensional-array,jagged-arrays,C#,Multidimensional Array,Jagged Arrays,C#中的多维数组double[,]和数组数组数组double[]之间有什么区别 如果存在差异,那么每种阵列的最佳用途是什么?阵列阵列(锯齿阵列)比多维阵列更快,可以更有效地使用。多维数组有更好的语法 如果您使用交错数组和多维数组编写一些简单代码,然后使用IL反汇编程序检查编译后的程序集,您将看到交错数组(或一维数组)的存储和检索数组是简单的IL指令,而多维数组的相同操作是总是较慢的方法调用 考虑以下方法: static void SetElementAt(int[][] array, int i

C#中的多维数组
double[,]
和数组数组数组
double[]
之间有什么区别

如果存在差异,那么每种阵列的最佳用途是什么?

阵列阵列(锯齿阵列)比多维阵列更快,可以更有效地使用。多维数组有更好的语法

如果您使用交错数组和多维数组编写一些简单代码,然后使用IL反汇编程序检查编译后的程序集,您将看到交错数组(或一维数组)的存储和检索数组是简单的IL指令,而多维数组的相同操作是总是较慢的方法调用

考虑以下方法:

static void SetElementAt(int[][] array, int i, int j, int value)
{
    array[i][j] = value;
}

static void SetElementAt(int[,] array, int i, int j, int value)
{
    array[i, j] = value;
}
他们的IL将如下所示:

.method private hidebysig static void  SetElementAt(int32[][] 'array',
                                                    int32 i,
                                                    int32 j,
                                                    int32 'value') cil managed
{
  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  ldelem.ref
  IL_0003:  ldarg.2
  IL_0004:  ldarg.3
  IL_0005:  stelem.i4
  IL_0006:  ret
} // end of method Program::SetElementAt

.method private hidebysig static void  SetElementAt(int32[0...,0...] 'array',
                                                    int32 i,
                                                    int32 j,
                                                    int32 'value') cil managed
{
  // Code size       10 (0xa)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  ldarg.2
  IL_0003:  ldarg.3
  IL_0004:  call       instance void int32[0...,0...]::Set(int32,
                                                           int32,
                                                           int32)
  IL_0009:  ret
} // end of method Program::SetElementAt

使用锯齿状数组时,可以轻松执行行交换和行大小调整等操作。在某些情况下,使用多维数组可能更安全,但即使是Microsoft FxCop也告诉我们,在使用交错数组分析项目时,也应该使用交错数组而不是多维数组。

简单地说,多维数组类似于DBMS中的表。
Array of Array(锯齿状数组)允许每个元素保存另一个相同类型的可变长度数组

因此,如果您确定数据结构看起来像一个表(固定的行/列),那么可以使用多维数组。锯齿状数组是固定元素&每个元素可以容纳一个可变长度的数组

例如,Psuedocode:

int[,] data = new int[2,2];
data[0,0] = 1;
data[0,1] = 2;
data[1,0] = 3;
data[1,1] = 4;
将上述内容视为2x2表格:

将上述情况视为每行的列数可变:


多维数组创建了一个很好的线性内存布局,而锯齿状数组意味着多个间接级别

在锯齿状数组中查找值
jagged[3][6]
var jagged=new int[10][5]
的工作方式如下:在索引3处查找元素(这是一个数组),在该数组中的索引6处查找元素(这是一个值)。对于本例中的每个维度,都有一个额外的查找(这是一种昂贵的内存访问模式)

多维数组在内存中线性排列,实际值是通过将索引相乘得到的。但是,给定数组
var mult=new int[10,30]
,该多维数组的
Length
属性返回元素总数,即10*30=300

锯齿数组的
Rank
属性始终为1,但多维数组可以有任何秩。任何数组的
GetLength
方法都可以用来获取每个维度的长度。对于本例中的多维数组,
mult.GetLength(1)
返回30

索引多维数组的速度更快。e、 g.给定本例中的多维数组
mult[1,7]
=30*1+7=37,获取该索引37处的元素。这是一种更好的内存访问模式,因为只涉及一个内存位置,即阵列的基址

因此,多维数组分配连续内存块,而锯齿数组不必是正方形,例如
锯齿[1]。长度
不必等于
锯齿[2]。长度
,这对于任何多维数组都是正确的

演出 就性能而言,多维阵列应该更快。速度要快得多,但由于CLR实现非常糟糕,所以它们不是

 23.084  16.634  15.215  15.489  14.407  13.691  14.695  14.398  14.551  14.252 
 25.782  27.484  25.711  20.844  19.607  20.349  25.861  26.214  19.677  20.171 
  5.050   5.085   6.412   5.225   5.100   5.751   6.650   5.222   6.770   5.305 
第一行是锯齿状数组的计时,第二行显示多维数组,第三行,应该是这样的。该程序如下所示,仅供参考。该程序在运行mono时进行了测试。(由于CLR实现的不同,windows的时间安排有很大的不同)

在windows上,锯齿状数组的计时非常优越,这与我自己对多维数组查找的解释大致相同,请参见“Single()”。遗憾的是,windows JIT编译器真的很愚蠢,不幸的是,这使得这些性能讨论变得困难,存在太多的不一致

这些是我在windows上得到的计时,这里的处理是一样的,第一行是锯齿状数组,第二行是多维数组,第三行是我自己的多维数组实现,请注意,与mono相比,windows上的执行速度要慢得多

  8.438   2.004   8.439   4.362   4.936   4.533   4.751   4.776   4.635   5.864
  7.414  13.196  11.940  11.832  11.675  11.811  11.812  12.964  11.885  11.751
 11.355  10.788  10.527  10.541  10.745  10.723  10.651  10.930  10.639  10.595
源代码:

using System;
using System.Diagnostics;
static class ArrayPref
{
    const string Format = "{0,7:0.000} ";
    static void Main()
    {
        Jagged();
        Multi();
        Single();
    }

    static void Jagged()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var jagged = new int[dim][][];
            for(var i = 0; i < dim; i++)
            {
                jagged[i] = new int[dim][];
                for(var j = 0; j < dim; j++)
                {
                    jagged[i][j] = new int[dim];
                    for(var k = 0; k < dim; k++)
                    {
                        jagged[i][j][k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }

    static void Multi()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var multi = new int[dim,dim,dim];
            for(var i = 0; i < dim; i++)
            {
                for(var j = 0; j < dim; j++)
                {
                    for(var k = 0; k < dim; k++)
                    {
                        multi[i,j,k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }

    static void Single()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var single = new int[dim*dim*dim];
            for(var i = 0; i < dim; i++)
            {
                for(var j = 0; j < dim; j++)
                {
                    for(var k = 0; k < dim; k++)
                    {
                        single[i*dim*dim+j*dim+k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }
}
使用系统;
使用系统诊断;
静态类ArrayPref
{
常量字符串格式=“{0,7:0.000}”;
静态void Main()
{
锯齿状();
多重();
单个();
}
静态空洞锯齿状()
{
常数int dim=100;
对于(var过程=0;过程<10;过程++)
{
var timer=新秒表();
timer.Start();
var jagged=新整数[dim][];
对于(变量i=0;i 23.084  16.634  15.215  15.489  14.407  13.691  14.695  14.398  14.551  14.252 
 25.782  27.484  25.711  20.844  19.607  20.349  25.861  26.214  19.677  20.171 
  5.050   5.085   6.412   5.225   5.100   5.751   6.650   5.222   6.770   5.305 
  8.438   2.004   8.439   4.362   4.936   4.533   4.751   4.776   4.635   5.864
  7.414  13.196  11.940  11.832  11.675  11.811  11.812  12.964  11.885  11.751
 11.355  10.788  10.527  10.541  10.745  10.723  10.651  10.930  10.639  10.595
using System;
using System.Diagnostics;
static class ArrayPref
{
    const string Format = "{0,7:0.000} ";
    static void Main()
    {
        Jagged();
        Multi();
        Single();
    }

    static void Jagged()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var jagged = new int[dim][][];
            for(var i = 0; i < dim; i++)
            {
                jagged[i] = new int[dim][];
                for(var j = 0; j < dim; j++)
                {
                    jagged[i][j] = new int[dim];
                    for(var k = 0; k < dim; k++)
                    {
                        jagged[i][j][k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }

    static void Multi()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var multi = new int[dim,dim,dim];
            for(var i = 0; i < dim; i++)
            {
                for(var j = 0; j < dim; j++)
                {
                    for(var k = 0; k < dim; k++)
                    {
                        multi[i,j,k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }

    static void Single()
    {
        const int dim = 100;
        for(var passes = 0; passes < 10; passes++)
        {
            var timer = new Stopwatch();
            timer.Start();
            var single = new int[dim*dim*dim];
            for(var i = 0; i < dim; i++)
            {
                for(var j = 0; j < dim; j++)
                {
                    for(var k = 0; k < dim; k++)
                    {
                        single[i*dim*dim+j*dim+k] = i * j * k;
                    }
                }
            }
            timer.Stop();
            Console.Write(Format,
                (double)timer.ElapsedTicks/TimeSpan.TicksPerMillisecond);
        }
        Console.WriteLine();
    }
}
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]
.method private hidebysig instance uint32[0...,0...] 
        GenerateWorkingKey(uint8[] key,
                           bool forEncryption) cil managed
Debug (code optimalization disabled)
Running jagged 
187.232 200.585 219.927 227.765 225.334 222.745 224.036 222.396 219.912 222.737 

Running multi-dimensional  
130.732 151.398 131.763 129.740 129.572 159.948 145.464 131.930 133.117 129.342 

Running single-dimensional  
 91.153 145.657 111.974  96.436 100.015  97.640  94.581 139.658 108.326  92.931 


Release (code optimalization enabled)
Running jagged 
108.503 95.409 128.187 121.877 119.295 118.201 102.321 116.393 125.499 116.459 

Running multi-dimensional 
 62.292  60.627  60.611  60.883  61.167  60.923  62.083  60.932  61.444  62.974 

Running single-dimensional 
 34.974  33.901  34.088  34.659  34.064  34.735  34.919  34.694  35.006  34.796 
  Debug:
  (Jagged)
  5.616   4.719   4.778   5.524   4.559   4.508   5.913   6.107   5.839   5.270
  
  (Multi)
  6.336   7.477   6.124   5.817   6.516   7.098   5.272   6.091  25.034   6.023
  
  (Single)
  4.688   3.494   4.425   6.176   4.472   4.347   4.976   4.754   3.591   4.403


  Release(code optimizations on):
  (Jagged)
  2.614   2.108   3.541   3.065   2.172   2.936   1.681   1.724   2.622   1.708

  (Multi)
  3.371   4.690   4.502   4.153   3.651   3.637   3.580   3.854   3.841   3.802

  (Single)
  1.934   2.102   2.246   2.061   1.941   1.900   2.172   2.103   1.911   1.911