C#类中方法的执行顺序
有些中级开发小伙伴还是搞不太明白在继承父类以及不同场景实例化的情况下,父类和子类的各种方法的执行顺序到底是什么,下面通过场景的举例来重新认识下方法的执行顺序:
(下面内容涉及到了C#中的继承,构造函数,虚方法,虚方法的重写,new关键字等知识点)
场景一
有子类继承,但是只实例化父类:只执行A对象,输出A对象的信息
class A
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
public void Fun() => Console.WriteLine("B的方法");
}
class Program
{
static void Main(string[] args)
{
A a = new A();
a.Fun();
Console.ReadLine();
}
}
上述Main方法中在new A对象时,程序首先进入class A中,执行class A的构造函数A(),然后执行class A中的Fun()方法,故运行结果为:

场景二
实例化子类,子类和父类的构造函数的执行顺序:当执行B对象时,因为继承A对象,所以首先执行基类A的构造函数
class A
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun()=> Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
public void Fun() => Console.WriteLine("B的方法");
}
class Program
{
static void Main(string[] args)
{
B b = new B();
b.Fun();
Console.ReadKey();
}
}
上述Main方法中在new B对象时,由于B继承A,先执行父类的构造函数,所以先执行A中的构造函数A(),然后在执行B中的构造函数B(),故运行结果为:

场景三
父类有虚方法,子类没有使用(override)关键字重写父类方法的时候,使用的是new关键字时:
class A
{
public A()=> Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
//不写new时,该方法会抛出警告,但不是错误
public new void Fun()=> Console.WriteLine("B的方法");
}
class Program
{
static void Main(string[] args)
{
A a = new B();
a.Fun();
Console.ReadKey();
}
}
上述Main方法中先new B对象,先执行A中的构造函数A(),然后在执行B中的构造函数B(),最后调用class A的Fun()方法(没有重写父类方法),故运行结果为:

场景四
父类有虚方法, 当子类重写了(override)父类的方法时:
class A
{
public A()=> Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B()=> Console.WriteLine("B的构造函数");
public override void Fun()=> Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
A a = new B();
a.Fun();
Console.ReadKey();
}
上述Main方法同样是先new B对象,先执行A中的构造函数A(),然后在执行B中的构造函数B(),但是子方法中使用了override关键字“覆盖”,使得子类中方法覆盖了父类中的方法,无法再访问父类中原始方法。(要重写方法,父类方法必须有virtual关键字),所以其运行结果为:

场景五
基类是接口层,多重继承时:
interface I
{
void Fun();
}
class A : I
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
//不写new时,该方法会抛出警告
public new void Fun() =>Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
B b = new B();
b.Fun();
((A)b).Fun();
((I)b).Fun();
Console.ReadKey();
}
打印结果:

场景六
当多重继承,子类重写override父类方法时:
interface I
{
void Fun();
}
class A : I
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A
{
public B() => Console.WriteLine("B的构造函数");
public override void Fun() =>Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
B b = new B();
b.Fun();
((A)b).Fun();
((I)b).Fun();
Console.ReadKey();
}
打印结果:(对比场景5)

场景七
使用new重写父类方法,同时让每个子类都继承接口:
interface I
{
void Fun();
}
class A : I
{
public A() => Console.WriteLine("A的构造函数");
public virtual void Fun() => Console.WriteLine("A的方法");
}
class B : A, I
{
public B() => Console.WriteLine("B的构造函数");
//不写new时,该方法会抛出警告
public new void Fun() => Console.WriteLine("B的方法");
}
static void Main(string[] args)
{
B b = new B();
b.Fun();
((A)b).Fun();
((I)b).Fun();
Console.ReadKey();
}
打印结果:

C#类中方法的执行顺序的更多相关文章
- 2018.11.20-day22 类中代码的执行顺序&组合
1.类中代码的执行顺序 2.组合
- Java组合与继承生成的类中构造函数的执行顺序
[程序实例] import java.util.*; class Meal{ Meal() { System.out.println("Meal Constructor"); } ...
- Java类中代码的执行顺序 静态代码块>构造代码块>构造方法
一:静态代码块 注意是代码块,不是静态函数.函数要调用才执行,代码块加载就执行,一般是静态变量的声明与初始化.被static修饰的代码块(赋值.输出操作等).类中静态语句块仅在类加载时被执行一次 如 ...
- Java中,类与类,类中的代码执行顺序
代码的执行顺序如下: 1.一个类的静态代码块.构造代码块.构造方法的执行流程为: 静态代码块 > 构造代码块 > 构造方法 2.静态的内容是随着类的加载而加载,静态代码块的内容会优先执行 ...
- java类中属性优先执行顺序
1.父类静态代码块 ( java虚拟机加载类时,就会执行该块代码,故只执行一次) 2 .子类静态代码块 ( java虚拟机加载类时,就会执行该块代码,故只执行一次) 3. 父类属性对象初始化 4. ...
- Java:面向对象(继承,方法的重写(overide),super,object类及object类中方法的重写,父子类代码块执行顺序)
继承: 1.继承是对某一匹类的抽象,从而实现对现实世界更好的建模. 2.提高代码的复用性. 3.extends(扩展),子类是父类的扩展. 4.子类继承父类可以得到父类的全部属性和方法.(除了父类的构 ...
- 在Spring Bean的生命周期中各方法的执行顺序
Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下十种: 通过实现 InitializingBe ...
- hadoop27---netty中handler的执行顺序
Netty是基于Java NIO的网络应用框架. Netty是一个NIO client-server(客户端服务器)框架,使用Netty可以快速开发网络应用,例如服务器和客户端协议.Netty提供了一 ...
- 7.Netty中 handler 的执行顺序
1.Netty中handler的执行顺序 Handler在Netty中,无疑占据着非常重要的地位.Handler与Servlet中的filter很像,通过Handler可以完成通讯报文的解码编码.拦截 ...
随机推荐
- OAuth2.0授权码模式实战
OAuth2.0是目前比较流行的一种开源授权协议,可以用来授权第三方应用,允许在不将用户名和密码提供给第三方应用的情况下获取一定的用户资源,目前很多网站或APP基于微信或QQ的第三方登录方式都是基于O ...
- [leetcode] 单调栈
本文总结单调栈算法. 原问题 学习一个算法,我们需要清楚的是:这个算法最原始的问题背景是什么样的? 下一个更小元素 给定一个数组 nums,返回每个元素的下一个更小的元素的下标 res,即 res[i ...
- Python基础之:Python中的内部对象
目录 简介 内置函数 内置常量 内置类型 逻辑值检测 逻辑值的布尔运算 比较运算 数字类型 整数类型的位运算 整数类型的附加方法 浮点类型的附加方法 迭代器 序列类型 集合类型 映射类型 字典视图对象 ...
- 全网最值得推荐的ELKB日志学习博客-博客地址留存
博客地址:https://elasticstack.blog.csdn.net/article/details/102728604 博客地址留存,后续解决疑难问题
- ls(list)命令详解及生产使用示例
文件有文件名与数据,在linux上被分为两个部分:用户数据(user data)与元数据(metadata) 用户数据,即文件数据块(data block),数据块是记录文件真实内容的地方,我们将其称 ...
- .Net Core发布到Linux下验证码失效处理方案详解
.net Core 部署到在 CentOS7下后,验证码打不开,报The type initializer for 'Gdip' threw an exception.异常 运行含图片处理时发生异常: ...
- 201871030139-于泽浩 实验二 个人项目D{0-1} KP
201871030139-于泽浩 实验二 个人项目D{0-1} KP 项目 内容 课程班级博客连接 2018级卓越班 这个作业要求连接 软件工程个人项目 我的课程学习目标 (1)掌握软件项目个人开发流 ...
- [Skill]从零掌握80%的业务查询SQL语句
前言 本篇文章的主要目的是帮助初学者快速入门SQL查询,从而解决实际业务中80%的SQL查询问题. 本文主要框架如下: 上篇:介绍SQL的语法顺序和执行顺序 中篇:介绍条件子句.分组查询和排序的细节 ...
- 华为云PB级数据库GaussDB(for Redis)揭秘第八期:用高斯 Redis 进行计数
摘要:高斯Redis,计数的最佳选择! 一.背景 当我们打开手机刷微博时,就要开始和各种各样的计数器打交道了.我们注册一个帐号后,微博就会给我们记录一组数据:关注数.粉丝数.动态数-:我们刷帖时,关注 ...
- Java中的绑定
1 前言 做了一次笔试题,发现了一题问答题,是关于Java绑定的: 当时做的时候是完全不会的... 于是这里补上一篇Java绑定的文章. 2 绑定 首先来了解一下绑定的概念.绑定是指一个方法的调用与方 ...