What's the magic of arrays in C#

后端 未结 8 1065
生来不讨喜
生来不讨喜 2020-12-09 08:56
int[] a = new int[5];
string[] b = new string[1];

The types of both a and b inherit from the abstract System.Array<

相关标签:
8条回答
  • 2020-12-09 09:46

    Trying to reason this out within the .NET type system doesn't get you very far. There is core support built into the JIT compiler and the CLR to deal with creating arrays. A statement like this:

            var arr = new int[5];
    

    Generates this IL:

      IL_0001:  ldc.i4.5
      IL_0002:  newarr     [mscorlib]System.Int32
    

    Which the JIT compiler then translate into this machine code:

    00000035  mov         edx,5                 ; arg2 = array size
    0000003a  mov         ecx,6F535F06h         ; arg1 = typeof(int)
    0000003f  call        FFD52128              ; call JIT_NewArr1(type, size)
    

    Core ingredients here are the dedicated IL opcode, newarr, instead of the usual newobj opcode that creates an instance of a class. And the simple translation to a CLR helper function that actually gets the object created. You can have a look-see at this helper function with the SSCLI20 source code, clr\src\vm\jithelpers.cpp. Too large to post here, but it is heavily optimized to make this kind of code run as fast possible, having direct access to the type internals available to CLR code.

    There are two of these helpers available, JIT_NewArr1() creates one-dimensional (vector) arrays and JIT_NewMDArr() creates multi-dimensional arrays. Compare to the two overloads available for Type.MakeArrayType().

    0 讨论(0)
  • 2020-12-09 09:47

    I went digging through the ECMA 335 spec, so I figured I'd share what I read.

    Exact array types are created automatically by the VES when they are required. Hence, the operations on an array type are defined by the CTS. These generally are: allocating the array based on size and lower-bound information, indexing the array to read and write a value, computing the address of an element of the array (a managed pointer), and querying for the rank, bounds, and the total number of values stored in the array.

    The VES creates one array type for each distinguishable array type.

    Vectors are subtypes of System.Array, an abstract class pre-defined by the CLI. It provides several methods that can be applied to all vectors. See Partition IV.

    While vectors (§II.14.1) have direct support through CIL instructions, all other arrays are supported by the VES by creating subtypes of the abstract class System.Array (see Partition IV)

    While vectors (§II.14.1) have direct support through CIL instructions, all other arrays are supported by the VES by creating subtypes of the abstract class System.Array (see Partition IV)

    The class that the VES creates for arrays contains several methods whose implementation is supplied by the VES:

    It goes on to state, quite verbosely, that the methods supplied are:

    1. Two constructors
    2. Get
    3. Set
    4. Address (returns a managed pointer)

    VES means Virtual Execution System, and the CLR is an implementation of it.

    The spec also details how to store the data of the array (contiguously in row-major order), what indexing is allowed in arrays (0-based only), when a vector is created (single dimensional, 0-based arrays) as opposed to a different array type, when the CIL instruction newarr is used as opposed to newobj (creating a 0-based, single dimensional array).

    Basically everything that the compiler has to do to build the method lookup tables etc.. for a regular type, it has to do for arrays, but they just programmed a more versatile and slightly special behavior into the compiler / JIT.

    Why did they do it? Probably because arrays are special, widely used, and can be stored in an optimized fashion. The C# team did not necessarily make this decision though. It's more of a .NET thing, which is a cousin to Mono and Portable.NET, all of which are a CIL thing.

    0 讨论(0)
提交回复
热议问题