ความแตกต่างระหว่างอาร์เรย์หลายมิติและอาร์เรย์ของอาร์เรย์ใน C # คืออะไร


454

อะไรคือความแตกต่างระหว่างอาร์เรย์หลายมิติdouble[,]และอาร์เรย์ของอาร์เรย์double[][]ใน C #

หากมีความแตกต่างอะไรคือการใช้ที่ดีที่สุดสำหรับแต่ละคน?


7
แรกdouble[,]คืออาร์เรย์สี่เหลี่ยมในขณะที่double[][]เรียกว่า "อาร์เรย์ขรุขระ" แรกจะมี "คอลัมน์" จำนวนเท่ากันสำหรับแต่ละแถวในขณะที่สองจะ (อาจ) มีจำนวน "คอลัมน์" ที่แตกต่างกันสำหรับแต่ละแถว
GreatAndPowerfulOz

คำตอบ:


334

Array of Array (Jagged Array) นั้นเร็วกว่าอาเรย์หลายมิติและสามารถใช้งานได้อย่างมีประสิทธิภาพมากขึ้น อาร์เรย์หลายมิติมีไวยากรณ์ที่ดีกว่า

หากคุณเขียนโค้ดอย่างง่ายโดยใช้อาร์เรย์แบบ jagged และหลายมิติแล้วตรวจสอบชุดประกอบที่รวบรวมด้วย disassembler 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 บอกว่าควรใช้อาร์เรย์ที่ขรุขระแทนมิติหลายมิติเมื่อคุณใช้เพื่อวิเคราะห์โครงการของคุณ


7
@ จอห์นวัดด้วยตัวคุณเองและอย่าตั้งสมมติฐาน
Hosam Aly

2
@ John: ปฏิกิริยาแรกของฉันด้วย แต่ฉันผิด - ดูคำถาม Hosams เพื่อดูรายละเอียด
Henk Holterman

38
อาร์เรย์หลายมิติควรมีประสิทธิภาพมากกว่า แต่การใช้งานโดยคอมไพเลอร์ JIT ไม่ใช่ โค้ดด้านบนไม่มีประโยชน์เนื่องจากไม่แสดงการเข้าถึงอาร์เรย์ในลูป
ILoveFortran

3
@Henk Holterman - ดูคำตอบของฉันด้านล่างมันอาจจะเป็นกรณีที่หน้าต่างขรุขระอาร์เรย์มีความรวดเร็ว แต่หนึ่งจะรู้ว่านี่เป็นเฉพาะ CLR ทั้งหมดและไม่ใช่กรณีที่มีเช่นขาวดำ ...
จอห์น Leidegren

12
ฉันรู้ว่านี่เป็นคำถามเก่าเพียงแค่สงสัยว่า CLR ได้รับการปรับให้เหมาะสมสำหรับอาร์เรย์หลายมิติหรือไม่นับตั้งแต่คำถามนี้ถูกถาม
Anthony Nichols

197

อาเรย์หลายมิติสร้างเลย์เอาต์หน่วยความจำเชิงเส้นที่ดีในขณะที่อาเรย์แบบหยักมีความหมายหลายระดับ

การค้นหาค่าjagged[3][6]ในอาเรย์ jagged จะ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

การจัดทำดัชนีอาร์เรย์หลายมิตินั้นเร็วกว่า เช่นกำหนดอาเรย์หลายมิติในตัวอย่างนี้mult[1,7]= 30 * 1 + 7 = 37 รับอิลิเมนต์ที่ดัชนีนั้น 37 นี่เป็นรูปแบบการเข้าถึงหน่วยความจำที่ดีกว่าเนื่องจากมีที่ตั้งหน่วยความจำเพียงแห่งเดียวซึ่งเป็นที่อยู่พื้นฐานของอาเรย์

อาร์เรย์หลายมิติจึงจัดสรรบล็อกหน่วยความจำอย่างต่อเนื่องในขณะที่อาร์เรย์แบบขรุขระไม่จำเป็นต้องเป็นรูปสี่เหลี่ยมเช่นjagged[1].Lengthไม่จำเป็นต้องเท่ากันjagged[2].Lengthซึ่งจะเป็นจริงสำหรับอาร์เรย์หลายมิติใด ๆ

ประสิทธิภาพ

ประสิทธิภาพที่ชาญฉลาดอาร์เรย์หลายมิติควรเร็วขึ้น เร็วกว่ามาก แต่เนื่องจากการใช้ 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 

แถวแรกคือการกำหนดเวลาของอาร์เรย์แบบขรุขระส่วนที่สองแสดงอาร์เรย์แบบหลายมิติและแถวที่สามนั่นคือสิ่งที่ควรจะเป็น โปรแกรมจะแสดงด้านล่าง FYI นี้ได้รับการทดสอบการทำงานโมโน (การกำหนดเวลา windows แตกต่างกันอย่างมากส่วนใหญ่เกิดจากรูปแบบการปรับใช้ CLR)

บน windows การกำหนดเวลาของอาร์เรย์แบบขรุขระนั้นเหนือกว่าอย่างมากเช่นเดียวกับการตีความของฉันเองเกี่ยวกับสิ่งที่อาร์เรย์หลายมิติควรดูให้ดู 'Single ()' น่าเศร้าที่คอมโพสิตของ JIT ของ windows นั้นโง่จริงๆและสิ่งนี้ทำให้การพูดคุยเรื่องประสิทธิภาพทำได้ยากมีความไม่สอดคล้องกันมากเกินไป

นี่คือการกำหนดเวลาที่ฉันได้รับบน 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();
    }
}

2
ลองจับเวลาด้วยตัวคุณเองและดูว่าทั้งสองทำงานกันอย่างไร อาร์เรย์แบบ Jagged ได้รับการปรับแต่งให้เหมาะสมใน. NET อาจเกี่ยวข้องกับการตรวจสอบขอบเขต แต่ไม่ว่าด้วยเหตุผลใดเวลาและเกณฑ์มาตรฐานแสดงให้เห็นอย่างชัดเจนว่าอาร์เรย์ที่ขรุขระนั้นเข้าถึงได้เร็วกว่าแบบหลายมิติ
Hosam Aly

10
แต่การกำหนดเวลาของคุณดูเหมือนจะเล็กเกินไป (ไม่กี่มิลลิวินาที) ในระดับนี้คุณจะได้รับการรบกวนจากบริการระบบและ / หรือไดรเวอร์มาก ทำให้การทดสอบของคุณมีขนาดใหญ่ขึ้นอย่างน้อยก็ใช้เวลาหนึ่งหรือสองวินาที
Hosam Aly

8
@ JohnLeidegren: ความจริงที่ว่าอาเรย์หลายมิติทำงานได้ดีขึ้นเมื่อทำดัชนีหนึ่งมิติกว่าอีกมิติหนึ่งซึ่งเป็นที่เข้าใจกันมานานครึ่งศตวรรษเนื่องจากองค์ประกอบที่แตกต่างกันในมิติเดียวจะถูกเก็บไว้ในหน่วยความจำอย่างต่อเนื่องและมีหน่วยความจำหลายประเภท และปัจจุบัน) การเข้าถึงรายการที่อยู่ติดกันนั้นเร็วกว่าการเข้าถึงรายการทางไกล ฉันคิดว่าใน. net หนึ่งควรได้รับการจัดทำดัชนีผลลัพธ์ที่ดีที่สุดโดยห้อยครั้งสุดท้ายซึ่งเป็นสิ่งที่คุณทำ
supercat

16
@supercat: อาร์เรย์หลายมิติใน C # ถูกเก็บไว้ในลำดับแถวหลักการสลับลำดับของตัวห้อยจะช้าลงเนื่องจากคุณจะเข้าถึงหน่วยความจำแบบไม่ต่อเนื่อง BTW เวลาที่รายงานไม่ถูกต้องอีกต่อไปฉันได้รับเกือบสองเท่าเร็วสำหรับอาร์เรย์หลายมิติกว่าอาร์เรย์ขรุขระ (ทดสอบกับ. NET CLR ล่าสุด) ซึ่งเป็นวิธีที่มันควรจะเป็น ..
Amro

9
ฉันรู้ว่านี่มันค่อนข้างเชื่องช้า แต่ฉันต้องพูดถึงว่านี่ไม่ใช่ Windows vs Mono แต่ CLR กับ Mono บางครั้งคุณอาจสับสน ทั้งสองไม่เท่ากัน Mono ใช้งานได้บน Windows เช่นกัน
Magus

70

เพียงแค่ใส่อาเรย์หลายมิติคล้ายกับตารางใน DBMS
Array of Array (jagged array) ช่วยให้คุณแต่ละองค์ประกอบมีอาเรย์อื่นที่มีความยาวตัวแปรชนิดเดียวกัน

ดังนั้นหากคุณแน่ใจว่าโครงสร้างข้อมูลดูเหมือนตาราง (แถวคงที่ / คอลัมน์) คุณสามารถใช้อาร์เรย์หลายมิติได้ อาร์เรย์ Jagged เป็นองค์ประกอบคงที่และแต่ละองค์ประกอบสามารถเก็บอาร์เรย์ความยาวของตัวแปรได้

เช่น Psuedocode:

int[,] data = new int[2,2];
data[0,0] = 1;
data[0,1] = 2;
data[1,0] = 3;
data[1,1] = 4;

คิดว่าข้างต้นเป็นตาราง 2x2:

1 | 2
3 | 4
int[][] jagged = new int[3][]; 
jagged[0] = new int[4] {  1,  2,  3,  4 }; 
jagged[1] = new int[2] { 11, 12 }; 
jagged[2] = new int[3] { 21, 22, 23 }; 

คิดว่าข้างต้นเป็นแต่ละแถวที่มีจำนวนคอลัมน์แปรผัน:

 1 |  2 |  3 | 4
11 | 12
21 | 22 | 23

4
นี่คือสิ่งที่สำคัญจริงๆเมื่อตัดสินใจว่าจะใช้ .. ความเร็วนี้ไม่ใช่สิ่งที่ดี .. ความเร็วที่ดีอาจกลายเป็นปัจจัยเมื่อคุณมีสแควร์อาเรย์
Xaser

46

คำนำ:ความคิดเห็นนี้มีจุดประสงค์เพื่อแก้ไขคำตอบที่ได้รับจาก okutaneแต่เนื่องจากระบบชื่อเสียงที่แย่มากของ SO ฉันจึงไม่สามารถโพสต์มันได้

การยืนยันของคุณว่าอันใดอันหนึ่งช้ากว่าอีกอันหนึ่งเนื่องจากวิธีการโทรไม่ถูกต้อง หนึ่งช้ากว่าอีกอันหนึ่งเนื่องจากอัลกอริธึมการตรวจสอบขอบเขตที่ซับซ้อนมากขึ้น คุณสามารถตรวจสอบสิ่งนี้ได้อย่างง่ายดายโดยดูที่ IL ไม่ใช่ แต่เป็นการรวบรวมที่รวบรวม ตัวอย่างเช่นในการติดตั้ง 4.5 ของฉันการเข้าถึงองค์ประกอบ (ผ่านตัวชี้ใน edx) เก็บไว้ในอาร์เรย์สองมิติที่ชี้ไปโดย ecx โดยมีดัชนีที่จัดเก็บใน eax และ edx มีลักษณะดังนี้:

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]

ที่นี่คุณจะเห็นว่าไม่มีค่าใช้จ่ายจากการเรียกใช้เมธอด การตรวจสอบขอบเขตนั้นซับซ้อนมากเนื่องจากความเป็นไปได้ของดัชนีที่ไม่ใช่ศูนย์ ถ้าเราเอาย่อย cmp และ jmps (x*y_max+y)*sizeof(ptr)+sizeof(array_header)สำหรับที่ไม่ใช่ศูนย์กรณีรหัสสวยมากหายไป การคำนวณนี้เร็วมาก (หนึ่งการคูณสามารถถูกแทนที่ด้วยกะเนื่องจากนั่นเป็นเหตุผลทั้งหมดที่เราเลือกไบต์ให้มีขนาดเป็นพลังของสองบิต) เป็นอย่างอื่นสำหรับการเข้าถึงองค์ประกอบแบบสุ่ม

ภาวะแทรกซ้อนอีกอย่างคือมีหลายกรณีที่คอมไพเลอร์สมัยใหม่จะปรับการตรวจสอบขอบเขตที่ซ้อนกันให้เหมาะสมสำหรับการเข้าถึงองค์ประกอบในขณะที่วนซ้ำแถวลำดับขนาดเดียว ผลลัพธ์คือโค้ดที่โดยทั่วไปแล้วจะเลื่อนตัวชี้ดัชนีไปยังหน่วยความจำต่อเนื่องของอาร์เรย์ การทำซ้ำแบบไร้เดียงสาในอาร์เรย์หลายมิติโดยทั่วไปเกี่ยวข้องกับเลเยอร์พิเศษของตรรกะที่ซ้อนกันดังนั้นคอมไพเลอร์จึงมีโอกาสน้อยที่จะปรับการทำงานให้เหมาะสม ดังนั้นแม้ว่าค่าใช้จ่ายในการตรวจสอบขอบเขตของการเข้าถึงองค์ประกอบเดียวจะลดค่าใช้จ่ายในการรันไทม์ที่คงที่เมื่อเทียบกับขนาดและขนาดอาเรย์กรณีทดสอบอย่างง่ายเพื่อวัดความแตกต่างอาจใช้เวลานานกว่าในการดำเนินการ


1
ขอบคุณสำหรับการแก้ไขคำตอบของ okutane (ไม่ใช่ Dmitry) มันน่ารำคาญที่ผู้คนให้คำตอบที่ผิดเกี่ยวกับ Stackoverflow และได้รับ 250 คะแนนขึ้นไปในขณะที่คนอื่น ๆ ให้คำตอบที่ถูกต้องและได้รับน้อยลง แต่ในตอนท้ายรหัส IL นั้นไม่เกี่ยวข้อง คุณต้องวัดความเร็วจริงๆเพื่อพูดอะไรเกี่ยวกับประสิทธิภาพ คุณทำเช่นนั้น? ฉันคิดว่าความแตกต่างจะไร้สาระ
Elmue

38

ฉันต้องการที่จะปรับปรุงเกี่ยวกับเรื่องนี้เพราะใน.NET หลักอาร์เรย์หลายมิติจะเร็วกว่าอาร์เรย์ขรุขระ ฉันรันการทดสอบจากJohn Leidegrenและนี่คือผลลัพธ์ใน. NET Core 2.0 Preview 2 ฉันเพิ่มค่ามิติเพื่อให้ได้อิทธิพลจากแอปพื้นหลังที่มองเห็นได้น้อยลง

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 

ฉันดูเป็นชิ้นส่วนและนี่คือสิ่งที่ฉันพบ

jagged[i][j][k] = i * j * k; ต้องการ 34 คำแนะนำในการดำเนินการ

multi[i, j, k] = i * j * k; ต้องการ 11 คำแนะนำในการดำเนินการ

single[i * dim * dim + j * dim + k] = i * j * k; ต้องการ 23 คำแนะนำในการดำเนินการ

ฉันไม่สามารถระบุสาเหตุที่อาร์เรย์แบบมิติเดียวยังคงเร็วกว่าแบบหลายมิติได้ แต่ฉันเดาว่ามันต้องทำอย่างไรกับการปรับให้เหมาะสมที่สุดที่ทำกับ CPU


14

อาร์เรย์หลายมิติคือเมทริกซ์ขนาด (n-1)

int[,] square = new int[2,2]แควร์เมทริกซ์ 2x2 int[,,] cube = new int [3,3,3]คือลูกบาศก์ - สแควร์เมทริกซ์ 3x3 สัดส่วนไม่จำเป็นต้องใช้

Jagged Array เป็นเพียงอาร์เรย์ของอาเรย์ - อาเรย์ที่แต่ละเซลล์มีอาเรย์

ดังนั้น MDA จึงเป็นสัดส่วน JD อาจไม่ใช่! แต่ละเซลล์สามารถมีความยาวได้ตามต้องการ!


7

สิ่งนี้อาจถูกกล่าวถึงในคำตอบข้างต้น แต่ไม่ชัดเจน: ด้วย jagged array คุณสามารถใช้array[row]เพื่ออ้างถึงแถวข้อมูลทั้งหมด แต่ไม่อนุญาตให้ใช้สำหรับอาร์เรย์หลาย d


4

นอกเหนือจากคำตอบอื่น ๆ โปรดทราบว่าอาเรย์หลายมิติถูกจัดสรรเป็นวัตถุขนาดใหญ่ก้อนเดียวบนกอง สิ่งนี้มีความหมายบางอย่าง:

  1. อาร์เรย์หลายมิติบางตัวจะได้รับการจัดสรรใน Large Object Heap (LOH) โดยที่อาร์เรย์แบบขรุขระของพวกมันจะไม่เท่ากัน
  2. GC จะต้องค้นหาบล็อกหน่วยความจำที่ต่อเนื่องกันเพื่อจัดสรรอาเรย์หลายมิติในขณะที่อาเรย์ jagged อาจเติมช่องว่างที่เกิดจากการแตกแฟรกเมนต์ฮีป ... นี่ไม่ใช่ปัญหาใน NET เนื่องจากการบีบอัด แต่ LOH จะไม่ถูกบีบอัดตามค่าเริ่มต้น (คุณต้องขอและคุณต้องถามทุกครั้งที่คุณต้องการ)
  3. คุณจะต้องมองหาวิธีการ<gcAllowVeryLargeObjects>หลายมิติอาร์เรย์ก่อนที่ปัญหาจะเกิดขึ้นหากคุณเคยใช้อาร์เรย์แบบขรุขระเท่านั้น

2

ฉันแยกวิเคราะห์ไฟล์. il ที่สร้างโดย ildasm เพื่อสร้างฐานข้อมูลของ assemnblies, คลาส, เมธอดและโพรซีเดอร์ที่เก็บไว้เพื่อใช้ในการแปลง ฉันเจอสิ่งต่อไปนี้ซึ่งทำให้การแยกวิเคราะห์ของฉันแตก

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

หนังสือ Expert .NET 2.0 IL Assembler โดย Serge Lidin, Apress ตีพิมพ์ในปี 2006 บทที่ 8 ประเภทดั้งเดิมและลายเซ็นหน้า 149-150 อธิบาย

<type>[]จะเรียกว่าเวกเตอร์<type>,

<type>[<bounds> [<bounds>**] ] ถูกเรียกว่าอาร์เรย์ของ <type>

**หมายถึงอาจจะทำซ้ำ[ ]หมายถึงตัวเลือก

ตัวอย่าง: <type> = int32Let

1) int32[...,...]เป็นอาร์เรย์สองมิติของขอบเขตและขนาดที่ต่ำกว่าที่ไม่ได้กำหนด

2) int32[2...5]เป็นอาร์เรย์หนึ่งมิติของขอบเขตล่าง 2 และขนาด 4

3) int32[0...,0...]เป็นอาร์เรย์สองมิติของขอบเขตที่ต่ำกว่า 0 และขนาดที่ไม่ได้กำหนด

ทอม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.