0

0

什么是构造器?引用类型是什么?

零下一度

零下一度

发布时间:2017-06-23 15:14:45

|

2759人浏览过

|

来源于php中文网

原创

引用类型
构造器是将类型的实例初始化为良好状态的特殊方法,创建引用类型的实例时,首先为实例的数据字段分配内存,然后初始化对象的附加字段(类型对象指针和同步块索引),最后调用类型的实例构造器来设置对象的初始化状态。
构造引用类型对象时,在电泳类型的实例构造器之前,为对象分配的内存总是先被归0,没有被构造器显示重写的所有字段都保证获得0或null值。
和其他方法不同,实力构造器永远不能被继承,也就是说,类只有类自己定义的还顺利构造器。由于永远不能继承实例构造器,所以实例构造器不能使用以下修饰符:Virtual,new,override,sealed和abstract。如果类没有显示定义任何构造器,C#编译器将默认一个默认无参构造器,在她的实现中,只是简单的调用了基类的无参构造函数。
如果类的修饰符为abstract,那么编译器生成的默认构造器的可访问性就为product;否则,构造器会被赋予public可访问属性。如果基类没有提供无参构造器,那么派生类必须显示调用一个基类构造器,否则编译器会报错。如果类的修饰符为static(sealed和abstract),编译器根本不会再类的定义中生成默认的构造器。
一个类型可以定义多个实例构造器。每个构造器都必须有不同的签名,而且每个都可以有不同的可访问属性。为了使代码“可验证”,类的实力构造器在访问从基类继承的任何字段前,必须先调用基类的构造器。如果派生类的构造器没有显示调用一个基类构造器,C#编译器会自动生成对默认的基类构造器的调用。最终,System.Object的公共无参构造器会得到调用。该构造器什么都不做,会直接返回,由于System.Object没有实例数据字段,所以它的构造器无事可做。
极少数情况下可以在不调用实例构造器的前提下创建类型实例。一个典型的例子就是Object的MemberwiseClone方法。该方法的作用是分配内存,初始化对象的附加字段,然后将源对象的自己数据复制到新对象中。另外,用运行时序列化器(runtime seriallizer)反序列化对象时,同程也不需要调用构造器。反序列化使用System.Runtime.Serialization.FormatterServices类型的GetUninitalizedObject或者GetSafeUninitailizedObject方法为对象分配内存,期间不会调用一个构造器。
 
提示:
不要再构造器中调用虚方法。原因是假如被实例化的类型重写了虚方法,就会执行派生类型对虚方法的实现,但是在这个时候,尚未完成对继承层次结构中所有字段的初始化(被实例化的类型的构造器还没有运行)。所以,调用虚方法会导致无法预测的行为。归根到底,这是由于调用虚方法时,直到运行时之前都不会选择执行该方法的实际类型。
 
值类型(struct)构造器
值类型(struct)构造器的工作方式与引用类型(class)的构造器截然不同。CLR总是允许创建值类型的实例,并且没有办法阻止值类型的实例化。所以,值类型其实并不需要定义构造器,C#编译器根本不会为值类型内联默认无参构造器。来看下面代码:
internal struct Point {
public int m_x, m_y;
}
 
internal sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
}
为了构造一个Rectangle,必须使用new操作符,而且必须指定构造器。在这个例子中,调用的是C#编译器自动生成的默认构造器。为Reatangle分配内存,内存中包含Point值类型的两个实例。考虑到性能,CLR不会为包含在引用类型中的每个值类型字段都主动调用构造器,但是,如前所述,值类型的字段都会被初始化为0或null。
CLR确实允许为值类型定义构造器,但是必须显示调用才会执行。
internal struct Point {
public int m_x, m_y;
 
public Point(int x, int y)
{
m_x = x;
m_y = y;
}
}
 
internal sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
this.m_TopLeft = new Point(1,2);
this.m_bottomRight = new Point(100,200);
}
}
 
值类型的实例构造器只有显示调用才会执行。因此,如果Rectangle的构造器没有使用new操作符来调用Point的构造器,从而初始化Reatangle的m_TopLeft和m_bottomRight字段,那么两个point字段中的m_x和m_y字段都将为0.
将上面代码改写:
internal struct Point {
public int m_x, m_y;
 
public Point()
{
m_x = 5;
m_y = 6;
}
}
 
internal sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
}
}
现在,构造新的Rectangle类时,两个Point字段中的m_x和m_y字段会被初始化多少,是0还是5?
可能你会觉得C#编译器会子啊Reactangel的构造器中生成代码,为Reactangel的两个字段自动调用Point的默认无参构造器。但是,为了增强应用程序的运行时性能,C#编译器不会自动生成这样的代码。实际上,即便值类型提供了无参构造器,许多编译器也永远不会生成代码来调用它,为了执行值类型无参构造器,开发人员必须增加显示调用值类型构造器的代码。但是会由于这个原因Point‘的两个字段被初始化为0吗?结果是:
 
 
C#编译器故意不允许值类型定义无参构造器,目的是防止开发人员对这种构造器在什么时候调用产生迷惑。由于不能定义无参构造器,所以编译器永远不会生成自动调用它的代码,没有无参构造器,值类型的字段总是被初始化为0或null。
 
类型构造器:
也称为静态构造器,类构造器或者类型初初始化器。类型构造器可应用与引用类型和值类型。实例构造器的作用是设置类型的实例的初始状态。对应的,类型构造器的作用是设置类型的初始状态。类型默认没有定义类型构造器,如果定义,也只能有一个。此外,类型构造器永远没有参数。
internal sealed class SomeRefType {
static SomeRefType()
{
//首次访问时,执行这里的代码
}
}
 
internal struct SomeValType
{
static SomeValType()
{
//首次访问时,执行这里的代码
}
}
可以看出,定义类型构造器类似于定义无参实例构造器,区别在于必须标记为static。此外,类型构造器总是私有的。之所以私有,是为了防止任何开发人员写代码调用它,对他的调用总是有CLR负责。
提示:
虽然能在值类型中定义类型构造器,但永远不要真的那么做,因为CLR有时不会调用值类型的静态构造器:例如
internal struct SomeValType
{
static SomeValType()
{
Console.WriteLine("这句话永远不会显示");
}
public int m_x;
}
class Program
{
static void Main(string[] args)
{
SomeValType[] a = new SomeValType[10];
a[0].m_x = 123;
Console.WriteLine(a[0].m_x);
Console.ReadKey();
}
}
类型构造器的代码只能访问类型的静态字段,并且他的非常规用途就是初始化这些字段。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 8.2万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

React 教程
React 教程

共58课时 | 4.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号