CLR via C# 方法 实例构造器和结构(值类型)

值类型(struct)构造器的工作方式与引用类型(class)的构造器截然不同。CLR总是允许创建值类型的实例,并且没有办法阻止值类型的实例化。所以,值类型其实并不需要定义构造器,C#编译器根本不会为值类型内联(嵌入)默认的无参构造器。

为了构造一个Rectangle,必须使用new操作符,而且必须指定构造器。在这个例子中,调用的是C#编译器自动生成的默认构造器。为Rectangle分配内存时,内存中包含Point值类型的两个实例。考虑到性能,CLR不会为包含在引用类型中的每个值类型字段都主动调用构造器。但是,值类型的字段会被初始化为0或null。

CLR确实允许为值类型定义构造器。但必须显式调用才会执行。

值类型的实例构造器只有显式调用才会执行。

即便值类型提供了无参构造器,许多编译器也永远不会生成代码来自动调用它。为了执行值类型的无参构造器,开发人员必须增加显式调用值类型构造器的代码。

C#编译器不允许值类型定义无参构造器。目的是防止开发人员对这种构造器在什么时候调用产生疑惑。

//--

注意:严格来说,只有当值类型的字段嵌套到引用类型中时,才保证被初始化为0或null。基于栈的值类型字段则无此保证。

但是,为了确保代码的“可验证性”(verifiability),任何基于栈的值类型字段都必须在读取之前写入(赋值)。允许先读再写会造成安全漏洞。对于所有基于栈的值类型中的字段,C#和其他能生成“可验证”代码的编译器可以保证对它们进行“置零”,或至少保证在读取之前赋值,确保不会在运行时因验证失败而抛出异常。所以,你可以忽略本“注意”的内容,假定自己的值类型的字段都会被初始化为0或null。

//--

注意:虽然C#不允许值类型带有无参构造器,但CLR允许。

由于C#不允许为值类型定义无参构造器,所以编译下面类型时,编译器将提示消息:

另外,为了生成“可验证”代码,在访问值类型的任何字段之前,都需要对全部字段进行赋值。所以,值类型的任何构造器都必须初始化值类型的全部字段。

为了修正这个问题,需要在构造器中为m_y赋一个值(通常是0)。下面是对值类型的全部字段进行赋值的一个替代方案:

有参构造器,看起来很奇怪,但是编译没问题,会将所有字段初始化为0或null。

在值类型的构造器中,this代表值类型本身的一个实例,用new 创建的值类型的一个实例可以赋给this。在new的过程中,会将所有字段置为零。而在引用类型的构造器中this被认为是只读的,所以不能对它进行赋值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值