这里直接给出C#类成员一般初始化顺序:

  1. 子类静态字段
  2. 子类静态构造
  3. 子类实例字段
  4. 父类静态字段
  5. 父类静态构造
  6. 父类实例字段
  7. 父类实例构造
  8. 子类实例构造

为什么说是“一般”初始化顺序呢?因为根据类结构的不同,类成员的初始化顺序并不是一成不变的。但是这个顺序是基础,可以推导出其他特殊的初始化顺序。下面我们就来看两种特殊的情况:

static void Main(string[] args)
{
Console.WriteLine("---------------一般初始化顺序---------------");
var child1 = new Child1();
Console.WriteLine("\n---------------子类静态字段初始化需要使用父类静态字段时初始化顺序---------------");
var child2 = new Child2();
Console.WriteLine("\n---------------子类静态构造函数中使用父类静态字段时初始化顺序---------------");
var child3 = new Child3(); Console.ReadKey();
} public class Child1 : Base1
{
public static Display ChildStatic = new Display("Child static filed"); private Display _childFiled = new Display("Child filed"); static Child1() => Console.WriteLine("Child static ctor"); public Child1() => Console.WriteLine("Child ctor");
} public class Child2 : Base2
{
/// <summary>
/// 子类静态字段初始化需要使用父类静态字段
/// </summary>
public static Display ChildStatic = new Display("Child static filed", () => BaseStatic); private Display _childFiled = new Display("Child filed"); static Child2() => Console.WriteLine("Child static ctor"); public Child2() => Console.WriteLine("Child ctor");
} public class Child3 : Base3
{
public static Display ChildStatic = new Display("Child static filed"); private Display _childFiled = new Display("Child filed"); /// <summary>
/// 子类静态构造函数中使用父类静态字段
/// </summary>
static Child3()
{
Console.WriteLine("Child static ctor");
var baseStatic = BaseStatic;
} public Child3() => Console.WriteLine("Child ctor");
} /// <summary>
/// 3个Base类相同,这里是为了演示静态成员的初始化
/// </summary>
public class Base1
{
public static Display BaseStatic = new Display("Base static filed"); private Display _baseFiled = new Display("Base filed"); static Base1() => Console.WriteLine("Base static ctor"); public Base1() => Console.WriteLine("Base ctor");
} public class Base2
{
public static Display BaseStatic = new Display("Base static filed"); private Display _baseFiled = new Display("Base filed"); static Base2() => Console.WriteLine("Base static ctor"); public Base2() => Console.WriteLine("Base ctor");
} public class Base3
{
public static Display BaseStatic = new Display("Base static filed"); private Display _baseFiled = new Display("Base filed"); static Base3() => Console.WriteLine("Base static ctor"); public Base3() => Console.WriteLine("Base ctor");
} public class Display
{
public Display(string msg, Func<Display> displayFunc = null)
{
Console.WriteLine(msg);
var display = displayFunc?.Invoke();
}
}



补充一下:

  • 静态构造函数是线程安全的,会在初次访问该类所定义的其他方法、属性或变量之前执行
  • 编译器会在每个构造函数(包括静态和实例)的开头放入适当的程序码,以便把你在定义成员字段时所指定的初始值设置给这些变量,这就是字段总是在构造函数执行前初始化的原因。
  • 无论是静态变量还是实例变量,其取值都应该在声明的时候得以初始化。但以下3种情况不应该编写初始化语句
    • 把字段初始化为0或null。因为系统在执行开发者编写的代码之前,就会把内存清零,重复执行清零指令就显得多余了
    • 字段的初始值需要根据不同的构造函数来设定。这种情况下字段的初始化放在构造函数中就可以了,否则会导致创建多余的对象
    • 字段的初始化过程中可能出现异常。这种也应该放在构造函数中进行初始化,同时要注意千万不能让静态构造函数中的异常脱出,因为一个AppDomain仅能调用一次某个类的静态构造函数

通过了解类成员的初始化顺序,可以让我们更加详细地了解程序执行的细节,避免写出类似“在构造函数中调用虚函数或抽象函数”的代码。

C#类成员初始化顺序的更多相关文章

  1. C#的类成员初始化顺序

    C#的类成员的定义和声明如下 using UnityEngine; using System.Collections; public class TestController : ECControll ...

  2. Java类成员初始化顺序

    类中包含7中成员:1.静态变量 static2.final静态常量 final static3.静态代码块 static{}  //多个代码块顺序执行 4.普通变量5.普通代码块 {}  //多个代码 ...

  3. java小心机(5)| 浅谈类成员初始化顺序

    类成员什么时候会被初始化呢?一般来说:"类的代码在初次使用时才被加载",加载过程包括了初始化. 比如说new A()调用构造函数时,类中全部成员都会被初始化. 但对于static域 ...

  4. C#类和类成员初始化顺序

    1.不带静态成员的普通类,首先通过构造函数初始化. 2.带静态属性的类,无论是普通类还是静态类,都会先初始化静态字段,再执行构造函数. 3.类初始化时,不会执行类中方法,无论是否是静态.若想执行方法, ...

  5. Java类的成员初始化顺序

    Java类的成员初始化顺序 2017-06-01 代码: public class InitializeSequence { public static void main(String[] args ...

  6. java类的成员初始化顺序和初始化块知识

    java类的成员初始化顺序和初始化块知识 转自:http://blog.csdn.net/lgfeng218/article/details/7606735 属性.方法.构造方法和自由块都是类中的成员 ...

  7. java类的初始化顺序

    在java中,当我们new一个对象时,对象中的成员,初始化块以及构造方法的加载是有一定的顺序的,看下面一副图: 一.单类(无基类)下的初始化顺序: public class Parent { stat ...

  8. C++成员初始化顺序

    #include <iostream> using namespace std; int seti() {cout << "seti" << e ...

  9. C#多态;父类引用指向子类对象;new和override的区别;new、abstract、virtual、override,sealed关键字区别和使用代码示例;c#类的初始化顺序

    关于父类引用指向子类对象 例如: 有以下2个类 public class Father { public int age = 70; public static string name = " ...

随机推荐

  1. .net reactor 学习系列(四)---.net reactor应用场景

    原文:.net reactor 学习系列(四)---.net reactor应用场景         前面已经学习了.net reactor一些基础知识,现在准备学习下实际的应用场景,只是简单的保护和 ...

  2. IIS基本介绍

    应用程序池-网站-应用程序   1 应用程序池 设置应用程序的各种设置,新建.修改应用程序的时候可以选择应用程序池   2 [站外图片上传中...(image-3924c8-1511163001873 ...

  3. 通通WPF随笔(3)——艺术二维码素材生成器

    原文:通通WPF随笔(3)--艺术二维码素材生成器 最近公司让我开发一个条形码的生成控件,花了半天时间搞定觉得不过瘾,什么年代了该用二维码了吧.于是wiki了一下二维码的资料. 比较常见的就是QR码( ...

  4. MVC EF Code First

    1 在Models里面创建类,用[Key]特性指定主键: 2 在Model里面增加导航属性: 3 在web.config里面增加连接字符串 4 创建继承于DbContext的类 5 创建Control ...

  5. siliverlight某些事件无法响应

    对一些无法响应的时间,需要注册 控件名:XZWT_TreeViewItem 事件:this.XZWT_TreeViewItem_MouseLeftButtonDown 具体注册方法: XZWT_Tre ...

  6. UWP应用载入SVG图片的兼容性方案

    原文 UWP应用载入SVG图片的兼容性方案 新版本<纸书科学计算器>的更新点之一,就是优化了表达式的显示方式.在旧版本中,表达式里的符号是用png图片显示的,当用户放大看的时候会发现一些锯 ...

  7. imp dll时遇见的非常恶心的问题

    我需要导入dll库中这样一个函数VM661JTCPDLL_API int admin_login(sel_admin_ret* sel_admins, int num, char* admin_nam ...

  8. C#try catch块

    try..catch块的出现是为了异常处理. 格式为:try{...可能发生异常的代码...} catch{...对异常的处理...} finaly{...无论如何都会执行的代码..} 上面的只是一般 ...

  9. 让Qt在MIPS Linux上运行 good

    下载 首先下载Qt everywhere,当前的版本是4.7.2,可以从nokia的网站上下载,也可以从git服务器上下载.考虑到文件有200M 以上的大小,下载速率低于25kBPS的,需要考虑从什么 ...

  10. linux下mysql定时备份

    1. 在服务器上建立备份文件的存放文件夹 sudo mkdir /usr/local/dbbackup 2. 编写备份脚本 vi dbbackup.sh 在里面编写如下内容 mysqldump -ur ...