實際上,與相關陣列插槽關聯的內存由值填充。給你的代碼一個小例子顯示了什麼發生。請在線查看評論。這是爲了發佈版本。
static void Main(string[] args)
{
Foo[] foos = new Foo[10];
foos[1] = new Foo(127, 255);
Console.ReadLine();
}
上述代碼被JIT編譯如下
// Method setup
00280050 55 push ebp
00280051 8bec mov ebp,esp
00280053 56 push esi
// Create instance of Foo[]
00280054 b98a141d00 mov ecx,1D148Ah
00280059 ba0a000000 mov edx,0Ah
0028005e e8b121f4ff call CORINFO_HELP_NEWARR_1_VC (001c2214)
00280063 8bd0 mov edx,eax
// Array range check
00280065 837a0401 cmp dword ptr [edx+4],1
00280069 7624 jbe
// Assign foos[1] = new Foo(127, 255)
0028006b 8d4210 lea eax,[edx+10h] <-- load location of foos[1] in eax
0028006e ba7f000000 mov edx,7Fh <-- load 127 in edx
00280073 beff000000 mov esi,0FFh <-- load 255 in esi
00280078 8910 mov dword ptr [eax],edx <-- move the value 127 to foos[1]
0028007a 897004 mov dword ptr [eax+4],esi <-- move the value 255 to foos[1] + offset
// This is just for the Console.ReadLine() part + rest of Main
0028007d e8d2436305 call mscorlib_ni!System.Console.get_In() (058b4454)
00280082 8bc8 mov ecx,eax
00280084 8b01 mov eax,dword ptr [ecx]
00280086 8b402c mov eax,dword ptr [eax+2Ch]
00280089 ff501c call dword ptr [eax+1Ch]
// Epilog
0028008c 5e pop esi
0028008d 5d pop ebp
0028008e c3 ret
//Exception handling
0028008f e8f05e7f70 call clr!JIT_RngChkFail (70a75f84)
00280094 cc int 3
總之
所以,代碼加載在寄存器中的常數,然後這些寄存器與的相關部分相關聯的存儲器的值複製數組實例。
據我記得,是的。結構是值類型,所以不是覆蓋foos [i]的引用(就像你看到的類),而是覆蓋整個結構在數組中的那個位置。垃圾收集器不必清理結構,因爲它被物理覆蓋。爲了測試,當Foo被聲明爲'struct'並且當它被聲明爲'class'時,計算Foo數組的大小,理論上,大小應該是'nElements * IntPtr.Size'類和nElements * sizeof(Foo)'爲結構體;但我從來沒有在C#中試過,所以我可能是錯的。 – 2012-07-06 02:11:09
我希望你能以某種方式使它成爲'new'直接覆蓋Foo對象,而不是創建並複製。 – SimpleVar 2012-07-06 02:13:14
@Yorye我認爲它會和聲明long i = 1 + 2一樣;值3從表達式(1 + 2)創建,然後複製到i中。所以真的,它與C風格語言通常的表現沒有什麼不同。 – CodeFusionMobile 2012-07-06 02:18:33