2009-10-11

Trzy sposoby inicjalizacji tablicy

Oto one:
public void Test()
{
    int[] ar1 = { 1, 2, 3 };
    int[] ar2 = new [] { 1, 2, 3 };
    int[] ar3 = new int[] { 1, 2, 3 };
}
A czym się różnią ? Niczym:
.method public hidebysig instance void Test() cil managed
{
    .maxstack 3
    .locals init (
        [0] int32[] ar1,
        [1] int32[] ar2,
        [2] int32[] ar3)
    L_0000: nop 
    L_0001: ldc.i4.3 
    L_0002: newarr int32
    L_0007: dup 
    L_0008: ldtoken valuetype <PrivateImplementationDetails>{014E1F63-D1B2-44CE-A8EC-8570A162FE16}/__StaticArrayInitTypeSize=12 <PrivateImplementationDetails>{014E1F63-D1B2-44CE-A8EC-8570A162FE16}::$$method0x600009b-1
    L_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
    L_0012: stloc.0 
    L_0013: ldc.i4.3 
    L_0014: newarr int32
    L_0019: dup 
    L_001a: ldtoken valuetype <PrivateImplementationDetails>{014E1F63-D1B2-44CE-A8EC-8570A162FE16}/__StaticArrayInitTypeSize=12 <PrivateImplementationDetails>{014E1F63-D1B2-44CE-A8EC-8570A162FE16}::$$method0x600009b-2
    L_001f: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
    L_0024: stloc.1 
    L_0025: ldc.i4.3 
    L_0026: newarr int32
    L_002b: dup 
    L_002c: ldtoken valuetype <PrivateImplementationDetails>{014E1F63-D1B2-44CE-A8EC-8570A162FE16}/__StaticArrayInitTypeSize=12 <PrivateImplementationDetails>{014E1F63-D1B2-44CE-A8EC-8570A162FE16}::$$method0x600009b-3
    L_0031: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
    L_0036: stloc.2 
    L_0037: ret 
}
Przy okazji można tutaj powiedzieć, że zawartość tych tablic trzymana jest w specjalnych globalnych zmiennych statycznych (jako ciąg bajtów). I kiedy istnieje konieczność skonstruowania takiej tablicy kopiowany jest tylko obszar pamięci. Kolejny pzykład:
public void Test(int x)
{
    int[] ar = {1, x};
    ar.ToString();
}
Kod IL:
.method public hidebysig instance void Test(int32 x) cil managed
{
    .maxstack 3
    .locals init (
        [0] int32[] ar,
        [1] int32[] CS$0$0000)
    L_0000: ldc.i4.2 
    L_0001: newarr int32
    L_0006: stloc.1 
    L_0007: ldloc.1 
    L_0008: ldc.i4.0 
    L_0009: ldc.i4.1 
    L_000a: stelem.i4 
    L_000b: ldloc.1 
    L_000c: ldc.i4.1 
    L_000d: ldarg.1 
    L_000e: stelem.i4 
    L_000f: ldloc.1 
    L_0010: stloc.0 
    L_0011: ldloc.0 
    L_0012: callvirt instance string [mscorlib]System.Object::ToString()
    L_0017: pop 
    L_0018: ret 
}
Widzimy, że w tym przypadku tworzenie zainicjalizowanej tablicy odbywa się poprzez jej utworzenie i ustawianiu indeks po indeksie jej zawartości. Podczas całego tego procesu referencja do tablicy przechowywana jest w zmiennej pomocniczej, dzięki czemu cały proces widziany z zewnątrz jest atomowy. Tak samo (inicjalizacja element po elemencie) dzieje się w przypadku tablic struktur i obiektów.

Brak komentarzy:

Prześlij komentarz