CLR在哪里存储一种类型实例的方法

时间:2014-11-27 11:03:23

标签: c# .net clr

class MyClass
{
     public string MyProperty { get; set; }

     public void MyMethod()
     {
          //Do something difficult here
          //100500 lines of code here ...
     }
}

我们有很多MyClass的实例。

CLR是否为类的任何实例创建了内存非常昂贵的MyMethod()

2 个答案:

答案 0 :(得分:5)

不,不。当我们第一次调用此方法时,此方法将编译一次。然后,编译的代码将由类型MyClass的任何实例使用。因此,只有在第一次调用此方法时才会发生任何性能损坏,IL代码将从本地编译为本机代码。

下面,我发布了两张可能更清晰的图片:

enter image description here

enter image description here

有关详细信息,请参阅本书CLR via C#

答案 1 :(得分:2)

假设你的意思

  

CLR是否为类的每个实例创建了这个内存非常昂贵的MyMethod()?

不,代码(对于类的方法)仅为每个方法生成一次。与MyClass的每个新实例关联的数据将存储在托管堆上,并且在实例上调用的每个方法都将silently pass the this实例的引用(指针)作为方法的隐藏参数。

以此片段为例:

var foo = new Foo();
var anotherFoo = new Foo();
foo.Bar();
anotherFoo.Bar();

反汇编显示了两个this引用如何作为参数传递给对同一Bar方法的调用。 (事实上​​,你可以看到同样的构造函数调用也是针对这两个对象的。)

            var foo = new Foo();
00000038  mov         ecx,592758h 
0000003d  call        FFC8F840
00000042  mov         dword ptr [ebp-4Ch],eax 
00000045  mov         ecx,dword ptr [ebp-4Ch] 
00000048  call        FFCA9F00 
0000004d  mov         eax,dword ptr [ebp-4Ch] 
00000050  mov         dword ptr [ebp-44h],eax ** [ebp-44h] = this for foo 
            var anotherFoo = new Foo();
00000053  mov         ecx,592758h 
00000058  call        FFC8F840
0000005d  mov         dword ptr [ebp-50h],eax 
00000060  mov         ecx,dword ptr [ebp-50h] 
00000063  call        FFCA9F00 
00000068  mov         eax,dword ptr [ebp-50h] 
0000006b  mov         dword ptr [ebp-48h],eax  ** [ebp-48h] = this for anotherFoo
            foo.Bar();
0000006e  mov         ecx,dword ptr [ebp-44h] ** pass foo to `Bar()` across in ecx
00000071  cmp         dword ptr [ecx],ecx 
00000073  call        FFCA9EF8   ** Bar()'s address
00000078  nop 
            anotherFoo.Bar();
00000079  mov         ecx,dword ptr [ebp-48h] ** pass anotherFoo to `Bar()` in ecx
0000007c  cmp         dword ptr [ecx],ecx 
0000007e  call        FFCA9EF8 ** You can see the same "Bar()" address is being called
00000083  nop