首页 后端开发 C#.Net教程 什么是构造器?引用类型是什么?

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

Jun 23, 2017 pm 03:14 PM

引用类型
构造器是将类型的实例初始化为良好状态的特殊方法,创建引用类型的实例时,首先为实例的数据字段分配内存,然后初始化对象的附加字段(类型对象指针和同步块索引),最后调用类型的实例构造器来设置对象的初始化状态。
构造引用类型对象时,在电泳类型的实例构造器之前,为对象分配的内存总是先被归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();
}
}
类型构造器的代码只能访问类型的静态字段,并且他的非常规用途就是初始化这些字段。

以上是什么是构造器?引用类型是什么?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

char在C语言字符串中的作用是什么 char在C语言字符串中的作用是什么 Apr 03, 2025 pm 03:15 PM

在 C 语言中,char 类型在字符串中用于:1. 存储单个字符;2. 使用数组表示字符串并以 null 终止符结束;3. 通过字符串操作函数进行操作;4. 从键盘读取或输出字符串。

C语言各种符号的使用方法 C语言各种符号的使用方法 Apr 03, 2025 pm 04:48 PM

C 语言中符号的使用方法涵盖算术、赋值、条件、逻辑、位运算符等。算术运算符用于基本数学运算,赋值运算符用于赋值和加减乘除赋值,条件运算符用于根据条件执行不同操作,逻辑运算符用于逻辑操作,位运算符用于位级操作,特殊常量用于表示空指针、文件结束标记和非数字值。

char在C语言中如何处理特殊字符 char在C语言中如何处理特殊字符 Apr 03, 2025 pm 03:18 PM

C语言中通过转义序列处理特殊字符,如:\n表示换行符。\t表示制表符。使用转义序列或字符常量表示特殊字符,如char c = '\n'。注意,反斜杠需要转义两次。不同平台和编译器可能有不同的转义序列,请查阅文档。

char与wchar_t在C语言中的区别 char与wchar_t在C语言中的区别 Apr 03, 2025 pm 03:09 PM

在 C 语言中,char 和 wchar_t 的主要区别在于字符编码:char 使用 ASCII 或扩展 ASCII,wchar_t 使用 Unicode;char 占用 1-2 个字节,wchar_t 占用 2-4 个字节;char 适用于英语文本,wchar_t 适用于多语言文本;char 广泛支持,wchar_t 依赖于编译器和操作系统是否支持 Unicode;char 的字符范围受限,wchar_t 的字符范围更大,并使用专门的函数进行算术运算。

c#多线程和异步的区别 c#多线程和异步的区别 Apr 03, 2025 pm 02:57 PM

多线程和异步的区别在于,多线程同时执行多个线程,而异步在不阻塞当前线程的情况下执行操作。多线程用于计算密集型任务,而异步用于用户交互操作。多线程的优势是提高计算性能,异步的优势是不阻塞 UI 线程。选择多线程还是异步取决于任务性质:计算密集型任务使用多线程,与外部资源交互且需要保持 UI 响应的任务使用异步。

char在C语言中如何进行类型转换 char在C语言中如何进行类型转换 Apr 03, 2025 pm 03:21 PM

在 C 语言中,char 类型转换可以通过:强制类型转换:使用强制类型转换符将一种类型的数据直接转换为另一种类型。自动类型转换:当一种类型的数据可以容纳另一种类型的值时,编译器自动进行转换。

char数组在C语言中如何使用 char数组在C语言中如何使用 Apr 03, 2025 pm 03:24 PM

char 数组在 C 语言中存储字符序列,声明为 char array_name[size]。访问元素通过下标运算符,元素以空终止符 '\0' 结尾,用于表示字符串终点。C 语言提供多种字符串操作函数,如 strlen()、strcpy()、strcat() 和 strcmp()。

C语言 sum 的作用是什么? C语言 sum 的作用是什么? Apr 03, 2025 pm 02:21 PM

C语言中没有内置求和函数,需自行编写。可通过遍历数组并累加元素实现求和:循环版本:使用for循环和数组长度计算求和。指针版本:使用指针指向数组元素,通过自增指针遍历高效求和。动态分配数组版本:动态分配数组并自行管理内存,确保释放已分配内存以防止内存泄漏。

See all articles