值类型实例不涉及到方法表操作,调用过程略显复杂,具体可以参考这篇博客
http://www.cnblogs.com/yangecnu/archive/2013/02/22/Value_Type_Internal.html
直接实例化结构调用方法就是了啊
方法随便调用,我问的是CLR是如何做到的?
即CLR是如何寻找到结构类型的方法入口的?
这是IL代码 调用方法的描述符....我也不是太懂 帮不到你
给你推荐一本书吧 你必须知道的.net 这本书 里面对值类型和应用类型的内存分配 有详细的讲解 或许可以得到你想要的答案
值类型在栈中,
引用在堆中.
而一个程序域中的情况无论什么类型,都进行描述.
LZ 这个问题提得太好了,让我花了一个中午找了好多资料,接触了很多新的知识,还与别人交流了意见,大致的结果如下,如有不对还望指出~谢谢啦~
先通过C# 代码与 IL代码来看
class Program { static void Main(string[] args) { test t = new test(); MyStruct myStruct = new MyStruct(); myStruct.PrintName("Zery"); } } struct MyStruct { public void PrintName(string name) { Console.WriteLine(name); } } internal class test { public void PirntName() { } }
IL 只列出关键部分
.locals init (class StructDemo.test V_0,
valuetype StructDemo.MyStruct V_1)
IL_0000: nop
IL_0001: newobj instance void StructDemo.test::.ctor()
IL_0006: stloc.0
IL_0007: ldloca.s V_1
IL_0009: initobj StructDemo.MyStruct
IL_000f: ldloca.s V_1
IL_0011: ldstr "Zery"
IL_0016: call instance void StructDemo.MyStruct::PrintName(string)
在执行Main这个方法时 会在线程栈的栈顶开辟一个Records Frame 的内存空间(此内存空间内的数据不遵循FILO原则)
现在看IL的第一条指令.locals init (class StructDemo.test V_0,valuetype StructDemo.MyStruct V_1)
定义了两个参数V_0与V_1类型分别为 test 和MyStruct类型
IL_0001: newobj instance void StructDemo.test::.ctor()
IL_0006: stloc.0
这两条进行实例化分配了内存空间并把指向堆中的地址赋值给了V_0,而我认为这个实例中应该是包含了方法的地址,
所以在实例调用方法时会与结构的实例调用方法一致,会有如下指令
IL_0016: call instance void StructDemo.MyStruct::PrintName(string) 注意是intance 实例的意思,只不过我用的结构的IL指令,实际上类的指令只是void StructDemo.MyStruct::PrintName(string)这一段会不一样而以,这个并不影响我们,
从上可以得出类的实例是包含了方法的地址的,所以可以调到方法 那结构呢?
从IL的指令上来说
IL_0007: ldloca.s V_1
IL_0009: initobj StructDemo.MyStruct
也是实现 实例化然后赋值给V_1
然后调用结构的方法
IL_0016: call instance void StructDemo.MyStruct::PrintName(string)
可以看到也是通过实例来调用的,也就是说结构的实例也有包含方法的址
但是我自己还是有点问题没有理解透
1 结构与类的方法是存在哪里的,是否类与结构都在各自的内存区域有一块方法表,用于存储方法,
2 自己还表达不出自己的问题。。。。。。
LZ如果对IL 不太了解 我有写过三篇IL的文章可供参考
以上为个人见解,如有不对还望指正~
在IL层值类型和引用类型对于方法的调用是没区别的,在IL层两者都已经找到了方法的地址,要想知道区别,得更底层一点。
一个变量包含3个部分:变量名、数据类型、值;程序编译后,所有变量名都会被替换为内存地址;结构和类一样,元数据会加载到内存中的LoaderHeap,其中包含有方法表(此时,数据类型也被替换为内存地址了);值与类型的对应关系应该是由编译器来维护的。期待楼下修正与补充……
晚上回去继续研究
是这样的,只要是一个类型,都会在应用程序域的一个堆上分配一块空间,这块空间是当第一次使用这个类型时分配的,这叫做类型的类型,同时静态变量(static)也是在此时进行分配的,这块内存空间记录了这个类型所有的静态变量和方法地址。当对象进行实例化,会有一个地址指向这个类型的类型对应的空间,当进行某个方法调用时,就可以找到这个方法的地址,这和你实例化的对象是分配在栈(值类型)上还是分配在堆(引用类型)上没有关系。
那我也有个问题,在创建对象的时候为类中成员去分配内存空间,那么方法是否也在这个时候被分配了内存空间呢?还有值类型数据一般存储在栈上,引用类型数据一般存放在堆中,那么方法是存放在栈中还是堆中呢?求大神...
值类型和引用类型的区别不是在于指针,每个变量都有指针的,之类型占的内存固定,而且少,在使用的时候直接把内存里的字节复制过去消耗也不会太大,引用类型往往占用的内存比较大,而且在使用的时候往往是当参数传来传去还想只控制一个对象,设计语言的时候就只给了一个地址。
这个估计要看内存分配了