C#类继承中构造函数的执行序列示例详解

作者:yixuan.han 时间:2022-05-26 11:42:09 

前言

大家都知道类的继承规则:

1、派生类自动包含基类的所有成员。但对于基类的私有成员,派生类虽然继承了,但是不能在派生类中访问。

2、所有的类都是按照继承链从顶层基类开始向下顺序构造。最顶层的基类是System.Object类,所有的类都隐式派生于它。只要记住这条规则,就能理解派生类在实例化时对构造函数的调用过程。

不知道大家在使用继承的过程中有木有遇到过调用构造函数时没有按照我们预期的那样执行呢?一般情况下,出现这样的问题往往是因为类继承结构中的某个基类没有被正确实例化,或者没有正确给基类构造函数提供信息,如果理解在对象生命周期的这个阶段发生的事情,将更利于解决此类问题。

为了实例化派生的类,必须先实例化它的基类。而要实例化这个基类。又必须要实例化这个基类的基类,这样一直到实例化System.Object(所有类的跟)为止,结果无论使用什么构造函数实例化一个类,总是首先调用System.Object.Object() .

下面一个示例演示执行顺序:

基类:


public class MyBaseClass
{
 public MyBaseClass()
 {
  Console.WriteLine("I am MyBaseClass()");
 }
 public MyBaseClass(int i)
 {
  Console.WriteLine("I am MyBaseClass(int i)");
 }            
}

派生类:


public MyDerivedClass()
 {
  Console.WriteLine("I am MyDerivedCalss()");
 }
 public MyDerivedClass(int i)
 {
  Console.WriteLine("I am MyDerivedClass(int i)");
 }
 public MyDerivedClass(int i,int j)
 {
  Console.WriteLine("I am MyDerivedClass(int i,int j)");
 }

接下来我们在Main函数中以不带参数的构造函数实例化MyDerivedClass:


MyDerivedClass myObj = new MyDerivedClass();

运行程序,控制台输出如下:

C#类继承中构造函数的执行序列示例详解

从结果可以看出,执行顺序先是基类构造的函数,接下来才是派生类的构造函数,即

1.执行System.Object.Object()构造函数(Object比较特殊,所有类的基类,一般可以不考虑,但是得知道它也是被执行了的)

2.执行MyBaseClass.MyBaseClass()构造函数

3.执行MyDerivedClass.MyDerivedClass()构造函数

如果我们以带一个参数的构造函数实例化MyDerivedClass:


MyDerivedClass myObj = new MyDerivedClass(4);

运行程序,控制台输出如下:

C#类继承中构造函数的执行序列示例详解

可以看出执行顺序如下:

1.执行System.Object.Object()构造函数

2.执行MyBaseClass.MyBaseClass()构造函数

3.执行MyDerivedClass.MyDerivedClass(int i)构造函数

同理如果我们以带两个参数的构造函数实例化MyDerivedClass


MyDerivedClass myObj = new MyDerivedClass(4,8);

运行程序,控制台输出如下:

C#类继承中构造函数的执行序列示例详解

可以看出执行顺序如下:

1.执行System.Object.Object()构造函数

2.执行MyBaseClass.MyBaseClass()构造函数

3.执行MyDerivedClass.MyDerivedClass(int i,int j)构造函数

大多数情况下这个都能正常工作,但是有时我们需要对发生的事件进行更多的控制。比如我们想得到如下所示的执行顺序:

1.执行System.Object.Object()构造函数

2.执行MyBaseClass.MyBaseClass(int i)构造函数

3.执行MyDerivedClass.MyDerivedClass(int i,int j)构造函数

使用这个顺序,可以把使用int i参数的代码放到MyBaseClass(int i)中,MyDerivedClass(int i,int j)只需要处理int j(假设int i参数在MyBaseClass和 MyDerivedClass里含义是一样的)

为此,只需要使用构造函数初始化器,把代码放到方法定义的冒号后面,如在派生类的构造函数中指定所使用的基类的构造函数,如下所示:


public MyDerivedClass(int i,int j) : base(i)
 {
  Console.WriteLine("I am MyDerivedClass(int i,int j)");
 }

其中,base关键字指定在实例化过程中使用具有指定参数的构造函数。这里使用了int参数,其值通过i传递给MyDerivedClass构造函数,所以将使用MyBaseClass(int i) ,这样就不会调用MyBaseClass()了,我们重新执行下前面两个参数的实例化代码,就可以看出执行结果确实如此:

C#类继承中构造函数的执行序列示例详解

除了base关键字,还可以使用this关键字用作构造函数初始化器,这个关键字指定在调用指定的构造函数前,实例化过程对当前类使用非默认的构造函数。例如:


public MyDerivedClass():this(5,6)
 {
  Console.WriteLine("I am MyDerivedCalss()");
 }

使用MyDerivedCalss()构造函数实例化,执行顺序是:

C#类继承中构造函数的执行序列示例详解

1.执行System.Object.Object()构造函数

2.执行MyBaseClass.MyBaseClass(int i)构造函数

3.执行MyDerivedClass.MyDerivedClass(int i,int j)构造函数

4.执行MyDerivedClass.MyDerivedClass()构造函数

总之呢,无论派生类上使用什么样的构造函数(默认的or不是默认的),除非明确指定(如使用base关键字),否则就先调用用基类的默认构造函数。

来源:https://www.cnblogs.com/yixuanhan/p/9596454.html

标签:c#,类继承,构造函数
0
投稿

猜你喜欢

  • 基于C#实现FTP下载文件

    2021-07-09 20:10:01
  • Java文件操作工具类fileUtil实例【文件增删改,复制等】

    2023-11-28 08:39:00
  • @Autowired注解注入的xxxMapper报错问题及解决

    2022-10-01 10:31:02
  • java实现通过绑定邮箱找回密码功能

    2021-12-17 00:16:48
  • File.createTempFile创建临时文件的示例详解

    2022-05-03 08:52:41
  • 使用okhttp替换Feign默认Client的操作

    2021-10-03 16:57:59
  • Java利用Dijkstra算法求解拓扑关系最短路径

    2021-08-24 10:30:54
  • SpringBoot集成Jpa对数据进行排序、分页、条件查询和过滤操作

    2022-03-06 19:17:50
  • swagger添加权限验证保证API(接口)安全性(两种方法)

    2023-11-27 18:58:33
  • java mybatis框架配置详解

    2023-11-25 08:09:16
  • java中的key接口解析

    2023-09-22 14:44:00
  • Java 用Prometheus搭建实时监控系统过程详解

    2023-09-06 12:07:40
  • Spring Boot2发布调用REST服务实现方法

    2023-12-10 20:03:49
  • 使用C语言的fork()函数在Linux中创建进程的实例讲解

    2023-07-07 04:40:24
  • Idea配置Maven阿里云镜像加速的实现

    2021-10-24 11:30:32
  • C#实现的json序列化和反序列化代码实例

    2022-04-05 22:24:08
  • SpringBoot 集成 activiti的示例代码

    2023-01-22 10:22:03
  • Java利用自定义注解实现数据校验

    2022-12-03 09:56:49
  • JDK源码之PriorityQueue解析

    2022-05-15 17:17:15
  • Spring创建bean对象三种方式代码实例

    2023-02-04 08:53:33
  • asp之家 软件编程 m.aspxhome.com