比如一个类
class A
{
int x=1;
public A()
{
x=4;
}
}
问:int x=1;这个赋值操作时在构造函数执行前的啥时候执行的?
我需要更正上一位贴图者的一点误解
ldarg.0 是指将图2中Call Stack中索引为0的参数加载到栈中
ldc.i4.1 是指将整数 1 作为int32类型加载到栈中
stfld 做一个赋值的操作,也就是完成 int x=1;这一个过程
此时 变量x的值就是1了 然后调用
call 指令 注意最后的 .ctor() 这个是引用类型初始化的指令
之后的操作就与前面一至了对x 进行赋值 x=4
从上面的过程来看 x=1 肯定是在构造函数之前就以经完成了初始化,而并不是在构造函数中完成初始化的
call 指令 注意最后的 .ctor() 这个是引用类型初始化的指令:这个调用的是基类object的构造函数,而不是这个类本身自己的构造函数。
从上面的过程来看 x=1 肯定是在构造函数之前就以经完成了初始化,而并不是在构造函数中完成初始化的 :所以你这个结论说在构造函数之前的结论不成立吧。
@乱舞春秋:
还好提醒 是基类object的构造函数,你没发现在调用基类的构造方法时
给x 赋为1 的IL指令就已经执行了吗? 所以最终还是在构造函数前就已经完成了初始化
@Zery:
所以最终还是在构造函数前就已经完成了初始化;
如果你这句话中的构造函数是指基类构造函数,那我赞同,但是这个和本类的构造函数根本就是两码事,。
如果你这句话中的构造函数是指本类构造函数,那么怎么就不是在构造函数内执行的x=1了;x=1,调用基类构造函数,x=4,这三个操作都是在本类的构造函数中完成。
@乱舞春秋: 现在和构造函数还没扯上关系,可以看图中
stfld int32 StaticDemo.A::X
这里的赋值操作针对的是A类中的x 变量
完了之后才调用Object的构造方法,如果你觉得是在Object基类中初始化的,或者在A类中初始化的,请拿出有力的证明,来证明我是错的,虽然我不能百分百肯定,但是没有理论证明我是错的前,我觉得我想法是正确的,欢迎一起深入探讨这个问题~
@Zery:
编译器会把实例变量的初始值设定放到本类的构造函数最开始位置;紧接着会安插对基类构造器的调用,然后再是你写在构造函数中的代码。
@乱舞春秋: 呃 终于出结论了,结果是 在构造函数内初始化的,其实我们贴出的IL 图就是A类的构造函数的
只是我过于观注IL 却忘了看这是哪个类的哪个方法了,实际上在new一个A的实例时 会先调用 A的构造完成初始化,而我们贴的IL图 就很明了的体现了初始化这一过程, 再次感谢 你的指正!
new 的时候执行。
可以去了解下.NET内存机制。
@Firen: 好的,好看看!
对的,类new时,分配堆栈空间时执行!
先执行x=1,再执行x=4,所以结果是x=4
你看看编译后的代码就明白了
class A
{
int x;
public A()
{
x=1;//会被安插在这里。
x=4;
}
}
如果编译后这这样的,x=1执行完后会立马执行x=4吧。。。
那这种情况
class A
{
public A()
{
PrintFields();
}
public virtual void PrintFields(){}
}
class B:A
{
int x=1;
int y;
public B()
{
y=-1;
}
public override void PrintFields()
{
Console.WriteLine("x={0},y={1}",x,y);
}
}
输出就不是x=1,y=0了吧。
@龙腾迷:
怎么不是x=1,y=0了,就是啊。
public B()
{
x=1;
a.PrintFields();//执行的是B类的,x=1,y=0,还未到y=-1。
y=-1;
}
@龙腾迷: 你这是c#语言规范 上的例子吧。
int x=1;对于你的A类,当你使用A a = new A();时,你创建了这个A的对象a,那么它就会立刻为A的所有字段分配存储空间(因为你的A没有继承其他类,不然当创建A对象时,它会先为顶层的父类中继承来的字段分配存储空间,然后层层往下递归最后才对A自身的字段进行内存分配,最高层类字段最先分配,也就是排在前面啦~),因为你这里只有一个x字段,那么是需要分配x的字段空间就好了。
然后就是方法表的创建,这个与你的问题暂时无关,就先不提了。
因为你已经给a对象的x字段分配了存储空间,当执行x=4的时候,x的引用地址中的x就会赋值为4,x是分配在堆栈上的哦,虽然他是值类型,但是它是类型的字段。
希望对你有用
可以推荐你看看《你必须知道的.Net2》这本书,解决了我当时学.Net的很多疑惑,也讲的比较易懂,尽管有的知识并没有被覆盖,但是绝对是一本好书
初始化类(全局变量会提前)->执行构造函数。
class A
{
public A()
{
Console.WriteLine(b);
b=5;
}
int b=3;
}
会输出3.
都好厉害
如果是新手的话,刚开始研究堆栈的话可能会有点晕,深层的东西先不用去研究,等你掌握的多了好好研究一下也不迟,你的问题答案楼上的已经说的很清楚了
实例化A类的时候给x分配堆栈的时候执行,建议先看一下基础的,堆栈比较难懂.