假设你的意思是
CLR 是否为类的每个 实例创建这个非常耗费内存的 MyMethod()?
不,类方法的代码只为每个方法生成一次。
但是,与类的每个新实例相关联的 数据 将被分配并存储在托管堆上(它定义了实例的this 位置),并且每个方法在一个类实例将silently pass the this实例的引用(指针)作为方法的隐藏参数。
以这个 sn-p 为例:
var foo = new Foo();
var anotherFoo = new Foo();
foo.Bar();
anotherFoo.Bar();
反汇编显示了两个this 引用如何作为参数传递给对同一Bar 方法的调用。 (实际上,您可以看到对两个对象也进行了相同的 Constructor 调用)。
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