《解析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元数据标记。【静态字段只要在访问之前初始化就可以了,具体什么时间无所谓。而显式类型构造器可能包含具有副作用的代码,所以需要在精确拿捏运行的时间】

解析C#类中的构造函数的更多相关文章

  1. Java反射机制demo(三)—获取类中的构造函数

    Java反射机制demo(三)—获取类中的构造函数 1,获取类中所有的构造函数 如下面的代码中所示,这个类中显式的构造函数有五个. 空构造: public UserInfo() 带参构造有四个: pu ...

  2. dart系列之:dart类中的构造函数

    目录 简介 传统的构造函数 命名构造函数 构造函数的执行顺序 重定向构造函数 Constant构造函数 工厂构造函数 总结 简介 dart作为一种面向对象的语言,class是必不可少的.dart中所有 ...

  3. java 中,new一个新对象时,是先给成员变量赋上初值后 再来调用类中的构造函数的。

    今天学习时法现一个问题,我们定义了一个Test类,在主类中new了一个他的对象,发现:在新建对象中所有的成员变量是先给定了默认初值的:0,null或者false, 之后再调用的构造函数.(如果变量是由 ...

  4. 【Android】解析Paint类中Xfermode的使用

    Paint类提供了setXfermode(Xfermode xfermode)方法,Xfermode指明了原图像和目标图像的结合方式.谈到Xfermode就不得不谈它的派生类PorterDuffXfe ...

  5. C++类中拷贝构造函数详解

    a. C++标准中提到"The default constructor, copy constructor and copy assignment operator, and destruc ...

  6. C#基础(五)——类中私有构造函数作用

    如果类成员有private修饰符,就不允许在类范围以外访问这个类成员.对类构造函数应用private修饰符时,则禁止外部类创建该类的实例.尽管看上去有些不好理解(既然不能实例化,那么这个类还有什么用处 ...

  7. hibernate多表查询,结果封装在自己定义的一个实体类当中(在自己定义的类中增加构造函数)

    hibernate的hql查询直接返回java对象时出现问题3 向大家请教一个问题,现在有三张表,表之间没有关联,我需要将三张表里面的所有东西查询出来存储到一个新的对象中,该如何实现,使用hibern ...

  8. Gson解析POJO类中的泛型参数

    在开发Android与API交互的时候,使用Json格式传输,遇到了这样一个情况,返回数据格式POJO类如下: public class ApiResult<T> { private in ...

  9. 【Android】解析Paint类中MaskFilter的使用

    目录结构: contents structure [+] EmbossMaskFilter BlurMaskFilter MaskFilter可以用来指定画笔的边缘效果.如果引用开启硬件加速的话,那么 ...

随机推荐

  1. Ionic实战 自动升级APP(Android版)

    Ionic 框架介绍 Ionic是一个基于Angularjs.可以使用HTML5构建混合移动应用的用户界面框架,它自称为是"本地与HTML5的结合".该框架提供了很多基本的移动用户 ...

  2. int (*p)[10] 与*p[10]的区别

    定义指向具有10个整型元素的一维数组的指针格式为:int (*p)[10] ,而起初我一直以为int (*p)[10] 是定义二维数组的方法 ][],(*p)[]; p=a; /*有了这个定义后,指针 ...

  3. ASP.NET Core Kestrel 中使用 HTTPS (SSL)

    在ASP.NET Core中,如果在Kestrel中想使用HTTPS对站点进行加密传输,可以按照如下方式 申请证书 这一步就不详细说了,有免费的和收费的,申请完成之后会给你一个*.pfx结尾的文件. ...

  4. 剑指Offer面试题:17.树的子结构

    一.题目:树的子结构 题目:输入两棵二叉树A和B,判断B是不是A的子结构.例如下图中的两棵二叉树,由于A中有一部分子树的结构和B是一样的,因此B是A的子结构. 该二叉树的节点定义如下,这里使用C#语言 ...

  5. [Voice communications] 声音的滤波

    本系列文章主要是介绍 Web Audio API 的相关知识,以及 web语音通信 中会遇到的一些问题,阐述可能存在错误,还请多多斧正! 通过设备获取音频流会不可避免的渗入一些杂音,这些杂音可能来自你 ...

  6. [nRF51822] 8、基础实验代码解析大全 · 实验11 - PPI

    前一篇分析了前十个基础实验的代码,从这里开始分析后十个~ 一.PPI原理: PPI(Programmable Peripheral Interconnect),中文翻译为可编程外设互连. 在nRF51 ...

  7. django开发个人简易Blog—nginx+uwsgin+django1.6+mysql 部署到CentOS6.5

    前面说完了此项目的创建及数据模型设计的过程.如果未看过,可以到这里查看,并且项目源码已经放大到github上,可以去这里下载. 代码也已经部署到sina sea上,地址为http://fengzhen ...

  8. Java 8函数编程轻松入门

    函数接口介绍 在Java1.8中,新增了Lambda表达式.在.net3.5(C# 3.0)在原先的匿名方法基础上演变出了Lambda表达式.学过C# Lambda表达式的同学,对于Java的Lamb ...

  9. ES6新特性之 promise

    新的ES6中引入了promise的概念,目的是让回调更为优雅.层层嵌套的回调会让javascript失去美感和可读性,同时javascript也推荐采用链式的方式去书写函数调用.于是Promise就应 ...

  10. Uiautomator 2.0之Configrator类学习小记

    1. Configration类介绍 1.1. Configrator用于设置脚本动作的默认延时 1.2  Configrator功能: 1.2.1 可调节两个模拟动作之间的默认间隔 1.2.2 可调 ...