Hallo,
Vorwort
ich habe mich danach umgesehen, wie ich am einfachsten eine List(T) mit Zahlen klonen kann, sodass eine Änderung in der zweiten Liste keine Auswirkungen auf die ursprüngliche Liste hat. Dabei stieß ich auf
In dieser Stackoverflow-Antwort und den beiden Kommentaren steht, dass das man ToList() verwenden kann, solange es sich um primitive Datentypen handelt. Mir ist bewusst, dass man bei Objekten eine tiefgehende Kopie (DeepClone) verwenden müsste, um unabhängige Kopien zu erhalten.
Anliegen
Ich habe mich nun interessehalber damit befasst, zu ergründen, was ToList eigentlich intern macht.
Mein VB.NET-Code erstellt zwei Listen, ListA und ListB. ListB wird durch die Verwendung der ToList()-Methode auf ListA erstellt.
Das ist der dazugehörige IL-Code. Bei Schritt Nr.
IL
Da ich noch nicht gesehen habe, inwiefern mit Pointern oder mit Kopien gearbeitet wird, habe ich mir den JIT-Asm-Code geben lassen.
JIT Asm
Hier habe ich leider keine Erfahrung, und brauche Hilfe. Sehe ich es richtig, dass sich mittels
Viele Grüße
Bartosz
Vorwort
ich habe mich danach umgesehen, wie ich am einfachsten eine List(T) mit Zahlen klonen kann, sodass eine Änderung in der zweiten Liste keine Auswirkungen auf die ursprüngliche Liste hat. Dabei stieß ich auf
ToList()
.In dieser Stackoverflow-Antwort und den beiden Kommentaren steht, dass das man ToList() verwenden kann, solange es sich um primitive Datentypen handelt. Mir ist bewusst, dass man bei Objekten eine tiefgehende Kopie (DeepClone) verwenden müsste, um unabhängige Kopien zu erhalten.
Anliegen
Ich habe mich nun interessehalber damit befasst, zu ergründen, was ToList eigentlich intern macht.
Mein VB.NET-Code erstellt zwei Listen, ListA und ListB. ListB wird durch die Verwendung der ToList()-Methode auf ListA erstellt.
Das ist der dazugehörige IL-Code. Bei Schritt Nr.
IL_001c
wird Liste B erstellt und mit Werten von A befüllt.Quellcode
- .assembly _
- {
- .custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = (
- 01 00 08 00 00 00 00 00
- )
- .custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = (
- 01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78
- 63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
- )
- .custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
- 01 00 02 00 00 00 00 00
- )
- .hash algorithm 0x00008004 // SHA1
- .ver 0:0:0:0
- }
- .class private auto ansi '<Module>'
- {
- } // end of class <Module>
- .class public auto ansi Form1
- extends [System.Runtime]System.Object
- {
- // Methods
- .method public specialname rtspecialname
- instance void .ctor () cil managed
- {
- // Method begins at RVA 0x2050
- // Code size 7 (0x7)
- .maxstack 8
- IL_0000: ldarg.0
- IL_0001: call instance void [System.Runtime]System.Object::.ctor()
- IL_0006: ret
- } // end of method Form1::.ctor
- .method private
- instance void Button1_Click () cil managed
- {
- // Method begins at RVA 0x2058
- // Code size 35 (0x23)
- .maxstack 8
- IL_0000: newobj instance void class [System.Collections]System.Collections.Generic.List`1<uint32>::.ctor()
- IL_0005: dup
- IL_0006: ldc.i4.1
- IL_0007: callvirt instance void class [System.Collections]System.Collections.Generic.List`1<uint32>::Add(!0)
- IL_000c: dup
- IL_000d: ldc.i4.s 10
- IL_000f: callvirt instance void class [System.Collections]System.Collections.Generic.List`1<uint32>::Add(!0)
- IL_0014: dup
- IL_0015: ldc.i4.s 100
- IL_0017: callvirt instance void class [System.Collections]System.Collections.Generic.List`1<uint32>::Add(!0)
- IL_001c: call class [System.Collections]System.Collections.Generic.List`1<!!0> [System.Linq]System.Linq.Enumerable::ToList<uint32>(class [System.Runtime]System.Collections.Generic.IEnumerable`1<!!0>)
- IL_0021: pop
- IL_0022: ret
- } // end of method Form1::Button1_Click
- } // end of class Form1
Da ich noch nicht gesehen habe, inwiefern mit Pointern oder mit Kopien gearbeitet wird, habe ich mir den JIT-Asm-Code geben lassen.
Quellcode
- ; Core CLR 7.0.1323.51816 on x86
- Form1..ctor()
- L0000: ret
- Form1.Button1_Click()
- L0000: push ebp
- L0001: mov ebp, esp
- L0003: push esi
- L0004: mov ecx, 0x103437a8
- L0009: call 0x00e4300c
- L000e: mov esi, eax
- L0010: mov ecx, 0x5d64c10
- L0015: mov edx, 0xad6
- L001a: call 0x71d500d0
- L001f: mov ecx, [0x8a52404]
- L0025: lea edx, [esi+4]
- L0028: call 0x00e10068
- L002d: inc dword ptr [esi+0xc]
- L0030: mov edx, [esi+8]
- L0033: cmp [ecx+4], edx
- L0036: jbe short L0048
- L0038: lea eax, [edx+1]
- L003b: mov [esi+8], eax
- L003e: mov dword ptr [ecx+edx*4+8], 1
- L0046: jmp short L0055
- L0048: mov ecx, esi
- L004a: mov edx, 1
- L004f: call dword ptr [0x1b9d5198]
- L0055: inc dword ptr [esi+0xc]
- L0058: mov ecx, [esi+4]
- L005b: mov edx, [esi+8]
- L005e: cmp [ecx+4], edx
- L0061: jbe short L0073
- L0063: lea eax, [edx+1]
- L0066: mov [esi+8], eax
- L0069: mov dword ptr [ecx+edx*4+8], 0xa
- L0071: jmp short L0080
- L0073: mov ecx, esi
- L0075: mov edx, 0xa
- L007a: call dword ptr [0x1b9d5198]
- L0080: inc dword ptr [esi+0xc]
- L0083: mov ecx, [esi+4]
- L0086: mov edx, [esi+8]
- L0089: cmp [ecx+4], edx
- L008c: jbe short L009e
- L008e: lea eax, [edx+1]
- L0091: mov [esi+8], eax
- L0094: mov dword ptr [ecx+edx*4+8], 0x64
- L009c: jmp short L00ab
- L009e: mov ecx, esi
- L00a0: mov edx, 0x64
- L00a5: call dword ptr [0x1b9d5198]
- L00ab: mov ecx, 0x103437a8
- L00b0: call 0x00e4300c
- L00b5: mov ecx, eax
- L00b7: mov edx, esi
- L00b9: call dword ptr [0x1b9d5030]
- L00bf: pop esi
- L00c0: pop ebp
- L00c1: ret
Hier habe ich leider keine Erfahrung, und brauche Hilfe. Sehe ich es richtig, dass sich mittels
L00b0: call 0x00e4300c
die Adresse von A geholt wird und dann Werte rüberkopiert werden, es aber einen Pointer auf 0x1b9d5030
gibt?Viele Grüße
Bartosz