public class staticClass
{
static private int _counter; private staticClass()
{
}
static staticClass()
{
counter = 0;
Console.Write("init!");
}
static public int counter
{
get
{
Console.Write("get!");
return _counter;
}
set
{
Console.Write("set!");
_counter = value;
}
}
}
则调用语句 staticClass.counter = 100; 的输出是( )通过运行程序,发现结果为“set! init! set! ” ,为什么?
{
static private int _counter; private staticClass()
{
}
static staticClass()
{
counter = 0;
Console.Write("init!");
}
static public int counter
{
get
{
Console.Write("get!");
return _counter;
}
set
{
Console.Write("set!");
_counter = value;
}
}
}
则调用语句 staticClass.counter = 100; 的输出是( )通过运行程序,发现结果为“set! init! set! ” ,为什么?
{
static private int _counter; private staticClass()
{
} static staticClass()
{
counter = 0;
Console.Write("init!");
} static public int counter
{
get
{
Console.Write("get!");
return _counter;
}
set
{
Console.Write("set!");
_counter = value;
}
}
}
我先把你的代码贴的易读点……
//给counter属性符值
set
{
Console.Write("set!"); ---2
_counter = value;
}
//调用静态构造函数
//因为静态构造函数在程序中只能执行一次,所以执行过程不会跳处的
static staticClass()
{
counter = 0;
Console.Write("init!"); ---3
}
//因为静态构造函数中又一次给counter属性符值
set
{
Console.Write("set!"); ---4
_counter = value;
}
在clr中,没有属性的概念,类型的成员只有:方法,字段和嵌套类.
C#中的属性,在被编译成msil的时候,属性都编译成了名称为 get_属性名,set_属性名的方法.
类型初始化器(静态构造函数)的运行时机,CLR有灵活的控制. 类型初始化器(静态构造函数)总是保证在首次访问类型的静态字段之前执行
具体有两种策略:
策略一(没有给类型添加beforefieldinit元数据): 在首次访问类型的静态字段之前执行
策略二(给类型添加了beforefieldinit元数据): 访问任何成员之前调用类型初始化器(静态构造函数) ---- 注:类型的成员包括:方法,字段和嵌套类
因为楼主的代码中显式的定义静态构造函数,所以代码被编译成中间语言的时候不会添加beforefieldinit元数据,所以对静态构造函数的调用将被推迟,只到有静态字段被访问之前.
当你给属性赋值的时候staticClass.counter = 100,首先执行的是类的构造函数:
static staticClass()
{
counter = 0;
Console.Write("init!");
}
进入以上构造函数,首先counter =0;由于counter是属性,所以触发了属性counter的set,这时就write 了"set!";
然后执行构造函数的Console.Write("init!");这时就write 了"init!";
执行完构造函数后,由于你给staticClass.counter 赋值100,所以又触发了属性counter的set,这时就write 了"set!";
连起来就是"set! init! set!”了