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