在C#中分配新的结构,以阵列时,会发生什么?(What happens when assign ne

2019-09-19 03:30发布

说我有一个C#的结构:

struct Foo{
    int mA;
    public int A {get {return mA;}}
    int mB;
    public int B {get {return mB;}}

    public Foo(int a, int b)
    {
        mA = a;
        mB = b;
    }
}

然后我创建和Foo的数组:

Foo[] foos = new Foo[10];

我这样做的时候会发生什么?

foos[1] = new Foo(20, 10);

如果富是一个类时,富[]将举行的指针在堆上一个Foo对象,并且该指针将被改变为新的Foo对象(被留回收旧的一个)。

但由于结构是值类型,将在新的Foo(20,10)只是物理覆盖以前的Foo [1]持有相同的内存位置?

Answer 1:

在实践中与相关阵列插槽相关联的存储器是由值填充。 鉴于你的代码的一个小例子显示了下去。 请参阅评论在线。 这是一个发布版本。

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

因此,在短期中,代码加载在寄存器中的常数,然后这些寄存器与阵列实例的相关部分相关联的存储器的副本的值。



Answer 2:

foos[1]将含有的逐位拷贝new Foo(20, 10);



Answer 3:

创建结构的阵列创建在每个时隙一个默认值的实例。 在C#中,要求new在C#中的结构创建一个新的临时实例(最有可能在栈上),并分配一个结构到另一个总是被改写后的所有字段与在相应的字段的内容发生变异后一种情况下前任的。 因此,语句foos[1] = new Foo(20,10); 创建一个新的临时实例Foo具有默认值,通过该实例的参数的构造函数,复制所有的临时的实例的在阵列插槽1举行的实例的字段,然后丢弃该临时实例。

顺便说一句,与相应的声明在vb.net的行为稍有不同。 说foos(1) = New Foo(20,10)将在所有领域的复位foos(1)为默认值,然后再传递foos(1)至参数的构造函数。 如果任何代码试图访问这种差异可以是显著foos(1)而构造正在运行。



文章来源: What happens when assign new struct to array in C#?