文档章节

解析C#类中的构造函数

彭泽0902
 彭泽0902
发布于 2016/11/24 18:47
字数 1966
阅读 9
收藏 0

《解析C#类中的构造函数》

一.  C#中的构造函数概述:

C#中类包含数据成员和函数成员。函数成员提供了操作类中数据的某些功能,包括方法、属性、构造器和终结器、运算符和索引器。

  1. 构造函数设计的定义

   构造器是允许将类型的实例初始化为良好状态的一种特殊方法。

  1. 2.    构造函数设计的作用:

c#中创建一个引用类型的实例时,首先为实例的数据字段分配内存,然后初始化对象的附加字段(类型对象指针和同步块索引),最后调用类型的实例构造器来设置对象的初始化状态。

  1. 3.    对类没有定义任何共有的或受保护的构造器,导致该类不能使用new在外部代码中实例化,此方式的作用:

     (1).类仅用作某些静态成员或属性的容器,因此永远不会实例化它。

(2).希望类仅通过调用某个静态成员函数来实例化(对象实例化工厂方法)

     4.基类构造函数的使用:

  编译器在调用基类的构造器前,会初始化任何使用了简化语法的字段,以维持源代码给人留下的“这些字段总是有一个值”的印象,如果基类的构造器调用了一个虚方法,它回调派生类中定义的一个方法,就可能出现问题。在这种情况下,用简化语法来初始化的字段在虚方法调用之前就已经初始化了。

二.  C#类中构造函数的分类:

  1. 1.    实例构造函数:

(1).实例构造函数概述:

声明一个与包含的类同名的方法,该方法没有返回类型。【如果没有提供任何构造函数,编译器会在后台创建一个默认的构造函数】

(2).实例构造函数的作用:

         A.把所有的成员字段初始化为标准的默认值。

B. 构造引用类型的对象时,在调用类型的实例构造器之前,为对象分配的内存总是先被归零,构造器没有显示重写的所有字段保证都有一个0或null值。实例构造器永远不能被继承。

C. 为了使代码“可验证”,类的实例构造器在访问从基类集成的任何字段之前,必须先调用基类的构造器。如果派生类的构造器没有显示调用一个基类构造器,C#编译器会自动生成对默认的基类构造器的调用。

  1. 2.    静态构造函数:

(1).静态构造函数概述:

静态构造函数(类型构造器、类型初始化构造器):静态构造函数(类型构造器)不能含有参数,没有修饰符,只能编写无参数的构造函数,这种构造函数只能执行一次,一个类也只能有一个静态构造函数,当前面的构造函数是实例构造函数,只要创建类的对象,就会执行它。

 (2).静态构造函数运行原理:

.NET运行库没有确保什么时候执行静态构造函数,所以不应该把要求在某个特定时刻执行的代码放在静态构造函数中。也不能预计不同类的静态构造函数按照什么顺序执行。

        (3).静态构造函数的调用:

    静态构造函数没有访问修饰符,其他C#代码从来不调用它,但是在类加载时,总是又.NET运行库调用它。静态构造函数只能访问类的静态成员,不能访问类的实例成员。

 3.构造函数使用范围:

     (1).无参数的实例构造函数与静态构造函数可以在同一类中同时定义,有参的实例构造函数与静态构造函数也可以在同一类中同时定义。【在类加载时执行静态构造函数,而在创建实例时执行实例构造函数】

    (2). C#编译器不允许值类型(结构)定义无参数的构造器,所以编译器永远不会生成自动调用它的代码,没有无参数构造器,值类型(结构)的字段总是被初始化为0或null。【C#不允许值类型(结构)定义无参数的构造器,但是CLR允许。C#运行值类型(结构)定义有参数的构造器】

三.  C#类中替代构造函数的方式:

1.在极少数情况下,可以在不调用实例构造器的前提下创建一个类型的实例。使用Object的MemberwiseClone方法,该方法的作用是分配内存,初始化对象的附加字段(类型对象指针和同步块索引),然后将源对象的字节数据复制到新对象中。

2.在用运行时序列化器反序列化对象时,通常也不需要调用构造器,反序列化使用FormatterService类型的GetUninitialzedObject或者GetSafeUninitializedObject方法为对象分配内存,期间不会调用一个构造器。

四.  C#类中构造器的使用情形:

  1.静态构造函数的使用:

     类中有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性。

2.构造函数的调用:

在C#类中,构造器可以调用其他构造器。C#构造函数初始化器可以包含对同一类的另一个构造函数的调用,也可以包含对直接基类的构造函数的调用。初始化器中不能有多个调用。【使用this关键字实现初始化器,调用参数最匹配的那个构造器】构造函数初始化器在构造函数的函数体之前进行。

五.  C#类中类型构造器的性能:

         1.     类型构造器的调用:

JIT编译器必须决定是否生成代码来调用它,而CLR必须确保对它的调用是线程安全的。

  1. 2.     JIT编译器在生成一个对类型构造器的调用,这个调用添加的位置情况:

(1).JIT编译器可以刚好在创建类型的第一个实例之前,或者刚好在访问类的一个非继承的字段或成员之前生成这个调用。即为精确语义。

(2).JIT编译器可以在首次访问一个静态字段或者一个静态/实例方法之前,或者在调用一个实例构造器之前,随便找一个时间生成调用。即为字段初始化前语义。

     3. .JIT对调用的位置选择:

  “字段初始化前”语义是首选的,因为它使CLR能够自由选择调用类型构造器的时机,而CLR会尽可能地利用这一点来生成运行得更快的代码。

4.C#编译器如果看到一个类(BeforeFieldInit)包含进行了内联初始化的静态字段,会在类的类型定义表中生成一个添加了BeforeFiledInit元数据标记的记录项。C#编译器如果看到一个类包含显示的类型构造器,就不会添加BeforeFiledInit元数据标记。【静态字段只要在访问之前初始化就可以了,具体什么时间无所谓。而显式类型构造器可能包含具有副作用的代码,所以需要在精确拿捏运行的时间】 

 

© 著作权归作者所有

共有 人打赏支持
彭泽0902
粉丝 0
博文 44
码字总数 57771
作品 0
武汉
高级程序员
MSIL学习------从HelloWorld开始

1.有没有必要学习IL   前段时间突然想搞搞IL语言,于是在博客园中找到了包建强前辈关于IL的文章学习,并且在包前辈博客里看到了09年他与赵劼前辈关于是否有必要学习IL语言的争论,作为一个...

莫问今朝乄
07/29
0
0
重新学.Net[八]——CLR的面向对象实现

懒了好几天,尽玩去了。恩,赶在年前,把想写的再写一点^_^。 .Net目的之一是建立一个面向对象的编程平台。CLR当然需要支持面向对象的各个特征,确切一些,CLR基本可以视为一个完全面向对象的...

余二五
2017/11/22
0
0
[C#基础知识]专题十三:全面解析对象集合初始化器、匿名类型和隐式类型

引言   经过前面专题的介绍,大家应该对C# 1和C# 2中的特性有了进一步的理解了吧,现在终于迎来我们期待已久的C# 3中特性,C# 中Lambda表达式和Linq的提出相当于彻底改变我们之前的编码风格了...

技术小胖子
2017/11/08
0
0
Unity3D_c#脚本注意要点

Inherit from MonoBehaviour 继承自MonoBehaviour All behaviour scripts must inherit from MonoBehaviour (directly or indirectly). This happens automatically in Javascript, but mus......

Matrix4X4
2012/06/26
306
0
提高 Unity 中 C# 代码质量的 21 条准则

本文作者:伯乐在线 -腾讯WeTest 。未经作者许可,禁止转载! 欢迎加入伯乐在线专栏作者。 本文将《Effective C# Second Edition》一书中适用于 Unity 游戏引擎里使用 C# 的经验之谈进行了提...

伯乐在线
2017/03/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

造谣造到t-io老巢了

只发当事人的截图,不发表评论,以免有引导嫌疑 PS1:截图是由不同的人发给我的 PS2:本人早就不在此微信群了 PS3:图3是2018-09-23的t-io官方群的一个发言小统计

talent-tan
9分钟前
15
0
heartbeat 资源

drbd+apache+heartbeat : http://blog.51cto.com/11838039/1827901 heartbeat双机热备的架设 : http://blog.51cto.com/11838039/1827560 对heaetbeat的深一步认识 : http://blog.51cto.co......

寰宇01
43分钟前
1
0
Spring 转换 model 为 json 时增加属性

缘起 目前的项目中有个需求是在附件对象转换成 json 时增加个 url 属性,以前的方式是在返回附件对象或列表时候做一次统一处理,这次想看看 spring 或者 jackson fasterxml 是否自带类似功能...

郁也风
今天
1
0
10大PHP比特币开源项目

如果你是一个Phper,如果你希望学习区块链,那么本文列出的 10个开源的Php比特币项目,将有助于你了解在自己的应用中 如何加入对比特币的支持。 如果你希望快速掌握使用Php对接比特币钱包的方...

汇智网教程
今天
1
0
springclould feign客户端添加全局参数

用springclould feign作为调用服务的客户端,一般来说参数可以写在feignclient的方法参数里 有时需要所有feign请求都统一添加一些参数,例如token用于鉴权等,可以这样做: 添加一个配置类,...

canneljls
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部