CLR via C#(06)- 构造器
最近忙着看新还珠,好几天不学习了。玩物丧志啊,罪过罪过。
今天总结的是类构造器的知识,其实这方面的文章蛮多的,可还是觉得亲自写一下对自己的思考和认识会有提高。
对于构造器,大家应该都不陌生,它主要是用来进行初始化状态的。包括实例构造器和类构造器两种,先给大家看个实际的例子。
class Dog : Animal
{
//字段
private string _name;
private int _age;
public string Name//属性
{
get { return _name; }
set { _name = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
public static string type = "动物";//静态字段
//实例构造器
public Dog() //①无参实例构造函数
{
_name = "无名";
}
public Dog(string name) //②重载,带参实例构造函数
{
this._name = name;
}
public Dog(string name, int age) //③显式调用其他构造函数
: this()
{
_age = age;
}
static Dog() //④类构造函数 (类构造器)
{
type = "狗狗";
}
}
class Animal//基类
{
public Animal()
{
Console.WriteLine("我是一只动物。");
}
}
一 实例构造器
实例构造器主要负责将类型的实例初始化到一个合理的状态。引用类型和值类型的实例构造器是有所区别的。
1. 引用类型实例构造器
实例构造器可以进行重载,而且可以具有不同的访问限制。上面例子中①②③都是引用类型实例构造器。
实例构造函数和类名相同,但是没有返回类型。在ILDasm.exe中查看为.ctor。
如果我们没有定义实例构造器,那么编译器会为我们默认产生一个无参构造器。
实例对象初始化过程
- 为实例分配内存;
- 初始化附加成员,包括方法表指针和SyncBlockIndex变量(我们已经在 跟小静读CLR via C#(03)中已经提到过)。
- 调用实例构造器进行初始化。
在调用构造函数前,变量被初始化为0或者null,所以没有被构造器改变的变量在实例创建后将保持0值。例如下面的age字段保持0值
调用顺序
如果类没有显示定义构造器,编译器会自动生成一个无参构造器,调用基类的无参构造器。例如
public class Animal{}
相当于
public class Animal
{
public Animal():base(){}
}
如果类的修饰符为static(sealed和abstract),编译器不会默认生成构造器;
如果基类没有提供无参构造器,那么派生类必须显示调用一个构造器,否则编译错误。
如果存在继承关系,派生类在使用基类的字段之前应该先调用基类的构造器。如果派生类没有显式调用基类构造器,则编译器会自动产生调用基类无参构造器的代码,沿着继承层次一直到System.Object的无参构造器位置。例如下面,调用Dog dog=new Dog()方法的结果。
class Dog:Animal。。。
Dog()方法IL代码
代码爆炸?
为了防止构造器重载时大量重复赋值造成代码膨胀,我们建议将公共的初始化语句放在一个构造函数中,然后其他的构造器显式调用该构造器。
2. 值类型实例构造器
- 值类型没有默认产生的无参构造器,也不允许我们定义无参构造器。但是我们可以自定义带参数的构造器。
- 不允许在值类型中内联实例字段的初始化。下面的例子会产生编译错误。
struct TestStruct
{
partial int number=5;
}
- 值类型带参构造函数必须对所有实例字段进行初始化才可以。如果有变量没有初始化,就会报错。
如果不想对所有字段一一初始化,有一种替代方案:
struct Dog
{
public int age;
public string name;
public Dog(string Name)
{
this = new Dog();
name = Name;
}
}
在值类型构造器中,this代表值类型本身的一个实例,用New创建的值类型实例赋给this时,会将所有字段置零。所以这个方案可以编译通过。
- 带参构造函数定义之后需要用new显式调用才能执行。否则值类型的字段会保持0或Null值。
二 类构造器
- 类构造器适用于引用类型(包括接口)和值类型,用来设置类的初始状态。类中并没有默认产生的类构造器,需要我们显式构造,标记为static方法。在元数据表中对应.cctor
- 类构造器只能有一个,不能进行重载。而且不能含参数。类构造器的目的是初始化类的静态成员,它只能访问静态成员,不能访问实例成员。
- 类构造器的访问限制是私有的,但是我们不能在类构造器前添加访问修饰符,private也不行,否则会产生编译错误,这样做是为了防止开发人员调用该方法。它的调用是由CLR负责的,我们应该避免编写需要以特定顺序调用类构造器的代码。
- 类构造器不要调用其基类的类构造器。因为基类的静态成员并没有被派生类所继承,它只是编译时静态绑定。
- 类构造器的调用顺序和实例构造器相似的,首先静态字段被初始化,然后在构造其中被重新赋值。例如:
class Dog : Animal
{
public static string type = "动物";//静态字段
//类构造函数
static Dog()
{
type = "狗狗";
}
}
Console.WriteLine(Dog.type);
本节小测
Dog的age字段值是什么呢?
A.0 B.5 C.其他
CLR via C#(06)- 构造器的更多相关文章
- CLR类型设计之方法与构造器
无论学习那门语言都要学习函数体,C#,JAVA,PHP,都会涉及到函数体,而C#的函数体成员并不少,方法和构造器就是函数体成员之一,函数体成员还包括但不限于:方法,属性,构造器,终结器,运算符及索引器 ...
- 6 CLR静态构造器
CLR保证一个类型构造器在每个AppDomain中只执行一次,而且这种执行是线程安全的. 作用: 就是初始化静态成员 比如有几个静态成员需要初始化那你把初始化代码放到哪呢? 放到普通构造函数里,那肯定 ...
- CLR via C#深解笔记四 - 方法、参数、属性
实例构造器和类(引用类型) 构造器(constructor)是允许将类型的实例初始化为良好状态的一种特殊方法.构造器方法在“方法定义元数据表”中始终叫.ctor. 创建一个引用类型的实例时: #1, ...
- [CLR via C#]8. 方法
一.实例构造器和类(引用类型) 类实例构造器是允许将类型的实例初始化为良好状态的一种特殊的方法. 类实例构造器方法在"方法定义元数据表"中始终叫.ctor(代表constructo ...
- C# 构造器总结
在C#中,构造器分为实例构造器和类型构造器, 一.实例构造器 构造引用类型的对象时,在调用实例 构造器之前,为对象分配的内存总是归0,没有被构造器显示重写的字段都保证获得0或null的值 在一个类中, ...
- CLR总览
Contents 第1章CLR的执行模型... 4 1.1将源代码编译成托管代码模块... 4 1.2 将托管模块合并成程序集... 6 1.3加载公共语言运行时... 7 1.4执行程序集的代码.. ...
- <NET CLR via c# 第4版>笔记 第8章 方法
8.1 实例构造器和类(引用类型) 构造引用类型的对象时,在调用类型的实例构造器之前,为对象分配的内存总是先被归零 .没有被构造器显式重写的所有字段都保证获得 0 或 null 值. 构造器不能被继承 ...
- [你必须知道的.NET]第二十三回:品味细节,深入.NET的类型构造器
发布日期:2008.11.2 作者:Anytao © 2008 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 今天Artech兄在<关于Type Init ...
- 重温CLR(六)方法和参数
实例构造器和类(引用类型) 构造器是将类型的实例初始化为良好状态的特殊方法.构造器方法在“方法定义元数据表”中始终叫做.ctor(constructor的简称).创建引用类型的实例时,首先为实例的数据 ...
随机推荐
- 真有用?Snap和Flatpak 通吃所有发行版的打包方式。
导读 最近我们听到越来越多的有关于Ubuntu的Snap包和由Red Hat员工Alexander Larsson创造的 Flatpak (曾经叫做 xdg-app)的消息.这两种下一代打包方法在本质 ...
- Caffe学习系列(15):添加新层
如何在Caffe中增加一层新的Layer呢?主要分为四步: (1)在./src/caffe/proto/caffe.proto 中增加对应layer的paramter message: (2)在./i ...
- HDU 1159 裸最长公共子串
试着拍了一道模板题 dp开了500,开100会超时..... string类型中间有空格会判为结束 #include<algorithm> -->min,max函数的头文件 #inc ...
- centos mysql 大量数据导入时1153 错误:1153 - Got a packet bigger than 'max_allowed_packet' bytes
参考:http://stackoverflow.com/questions/93128/mysql-error-1153-got-a-packet-bigger-than-max-allowed-pa ...
- speex介绍
1介绍 Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式.Speex工程着力于通过提供一个可以替代高性能语音编解码来降低语音应用输入门槛 .另外,相对于其它编解码器,Speex也很适合 ...
- apache开启虚拟主机localhost无法访问
今天在集成环境下配虚拟主机,没想到虚拟主机开启后,localhost竟然无法访问了,解决办法是这样的: 实例一,Apache 配置localhost虚拟主机步骤 1,用记事本打开apache目录下ht ...
- php中的钩子(hook插件机制)
对"钩子"这个概念其实不熟悉,最近看到一个php框架中用到这种机制来扩展项目,所以大概来了解下. hook插件机制的基本思想: 在项目代码中,你认为要扩展(暂时不扩展)的地方放置一 ...
- C#零碎知识汇总
1.1取时间差 时刻:DateTime 时差:TimeSpan 代码: DateTime time1 = DateTime.Now; textBox1.Text = time1.ToStri ...
- subprocess模块在Windows下调用失败问题
bug of pythonhttp://bugs.python.org/issue1759845 解决:print sys.stdout.encoding #eg : it shows cp936i ...
- Gitlab的Gravatar头像无法显示的问题
通过gitlab搭建的git仓库,由于Gravatar被墙了,导致Gravatar头像无法显示.总觉得怪怪的. 社区版gitlab解决办法: vi /var/opt/gitlab/gitlab-rai ...