深入解析值类型的初始化过程!
大家看一个结构体定义:
struct Book
{
public string author;
public Book(string author)
{
this.author = author;
}
public string Author
{
get { return author; }
set { author = value; }
}
}
下面是初始化代码:
static void Main(string[] args)
{
Book b;
b.author = "asdf";
}
这段代码可以通过编译,当然如果把struct换成class,马上就会发生编译错误了:使用了未赋值的局部变量b.
为什么struct变量可以不通过Book b=new Book()的方式而使用字段呢?
大师Jeffery在他的书中解释了类似的现象,实际上对于struct来说:
Book b;
Book b=new Book();
在本质上这两行代码没有区别,都会把实例分配在线程堆栈上,并产生把所有字段置0(二进制意义上的0)的IL指令,但是为什么通过Book b;这样的方式来初始化,以后访问其他成员会导致编译错误呢?
比如:b.Author="asdf";//这里访问属性Author,会发生编译错误
原因是C#编译器“认为”设置public字段是初始化行为,而设置属性不是初始化行为,的编译检查,你通过Book b=new Book();来初始化会让编译器认为b已经初始化了!
大家可能认为Book b=new Book();会调用Book的默认无参构造函数,实际上并非如此,对于struct来说,C#编译器并不会像引用类型那样产生默认的无参构造函数,而且为了避免混淆,也不允许我们自己为struct定义无参构造函数!
作为一种良好的编程习惯,也为了避免不必要的误解,还是建议直接使用Book b=new Book();这样的方式来初始化struct变量!
对于其他值类型,C#给我们提供了更简单的初始化语法,比如:
int i=0;