美文网首页.NET程序员
C#中为什么会出现空静态构造方法的写法

C#中为什么会出现空静态构造方法的写法

作者: CoderBear | 来源:发表于2019-02-02 11:02 被阅读2次

再过几个小时,就要回家过春节了,今天说些简单点的东西,大家在看C#代码的时候,一定会对这样的写法非常迷茫:在一个类中会出现一个空的静态构造方法。这不是多此一举吗,这样做的目的是什么?今天我就来说说这个内容。

前段时间,小伙伴遇到一个问题,百思不得其解,我先来模拟下这个问题:

 class Program
    {
        static void Main(string[] args)
        {
            //1.初始化配置中心
            Console.WriteLine("初始化配置中心");
           
            //2.利用从配置中心读取出来的内容进行了一些操作
             String config= MyTest.config;
            //dosomething
        }
    }
    public class MyTest
    {
        public static string config = getConfig();

        private static string getConfig()
        {
            //读取配置中心的内容,并返回
            return "";
        }
    }

代码比较简单,就是有两个类,一个是主程序入口,一个是业务类,在业务类里面,定义了一个static的变量,给它赋上一个方法,方法中读取了配置中心的内容,并且返回,那么这个static的变量的值就是配置中心的内容了,在主程序入口,一开始就初始化了配置中心,然后访问在业务类中的静态变量,并且利用这个值,做一些后续操作。

我们先不管这样的逻辑是否合理,就只看能否正常运行。

这样的代码看上去并没有什么问题,但是让人不解的是,抛出了异常,内容是“配置中心未初始化”,小伙伴懵了,明明一开始就初始了配置中心啊,为什么读取配置中心内容的时候,还会出现这样的异常呢。

我一看,立刻懂了,于是我在业务类中,加了一个静态的构造方法,如下所示:

    public class MyTest
    {
        public static string config = getConfig();

        private static string getConfig()
        {
            //读取配置中心的内容,并返回
            return "";
        }

        static MyTest() { }
    }

一切都好了。

我加了一个空的静态方法,注意是空的,为什么加了一个空的静态方法可以解决问题呢?我们再来做个试验把:

    class Program
    {
        static void Main(string[] args)
        {
            //初始化配置中心
            Console.WriteLine("初始化配置中心");

            //2.利用从配置中心读取出来的内容进行了一些操作
            String config = MyTest.config;
            Console.WriteLine(config);
        }
    }
  public class MyTest
    {
        public static string config = getConfig();

        private static string getConfig()
        {
            Console.WriteLine("进到了getConfig方法");
            //读取配置中心的内容,并返回
            return "配置中心的内容";
        }
    }

让我们想想会输出什么?这还不简单,当然是 初始化配置中心 进到了getConfig方法 配置中心的内容,但是,当我们运行:


image.png

你会发现,奇怪的事情出现了,第一个输出的竟然是 进到了“getConfig方法”。

我们为MyTest类加上一个空的静态构造方法,再看看:

 public class MyTest
    {
        public static string config = getConfig();

        private static string getConfig()
        {
            Console.WriteLine("进到了getConfig方法");
            //读取配置中心的内容,并返回
            return "配置中心的内容";
        }

        static MyTest() { }
    }
image.png

输出竟然被改变了。

这就是解释了为什么小伙伴一开始的代码会出现问题的原因,因为程序一上来,还没有执行 初始化配置中心呢,直接读取了配置中心的内容,而我加上的空静态构造方法,就改变了代码的执行顺序,是不是很神奇。

我们在用ILSpy看下IL代码,当类中没有静态构造方法的时候:


image.png

IL代码有一个标记:beforefieldinit

当类中的静态构造方法的时候:


image.png

beforefieldinit标记消失了。

我们来做一个总结,当一个类中没有静态构造方法的时候,IL会有beforefieldinit标记,程序一运行,就会初始化静态字段,当一个类中有静态构造方法的时候,IL没有beforefieldinit标记,程序一开始就不会初始化静态字段,而是用到这个类了,才初始化静态字段。

现在我们可以解释为什么在饿汉式的单例模式中,经常会看到空的静态构造方法了,因为不想让程序在一开始的时候就初始化这个单例对象,而是用到了才去初始化,相当于懒加载,其实这也是一种优化,如果程序运行后,长时间没有使用到这个单例对象,而一开始程序就把单例对象加载到内存中去了,也是一种浪费。

这篇的内容到这里就结束了,哈哈,马上就解放啦。

相关文章

  • C#中为什么会出现空静态构造方法的写法

    再过几个小时,就要回家过春节了,今天说些简单点的东西,大家在看C#代码的时候,一定会对这样的写法非常迷茫:在一个类...

  • 单例:全局事件注册,只产生一个对象,节约内存

    C#单例的写法: (1)私有化构造方法 (2)内建静态实例 (3)公开静态方法给实例做初始化 在Unity中的运用...

  • super

    super:关键字 与this对比学习this:出现在实例方法中和构造方法中,不能出现在静态方法中。this(),...

  • SpringBoot @PostConstruct注解

    依赖注入后将调用被@PostConstruct修饰的方法像静态方法,或构造方法中调用被注入的对象,则该对象为空构造...

  • Lombok高级用法

    bean中的链式风格 关键词@Accessors最佳实践 静态构造方法 构造参数为空的最佳实践 构造参数为name...

  • C#中的静态构造函数和静态初始化器

    网站收藏 C井中的静态构造函数和静态初始化器 C#给类的静态成员初始化必须用静态构造函数 关于Type Initi...

  • 第二章 Java与Kotlin的写法比较

    3 Java与Kotlin的写法比较 3.1 构造器、变量、常量和静态数据 3.1.1 构造函数 java中的构造...

  • 05 - 单例模式

    定义: 某一种对象,全局只能创建一个。 单例模式犹如茴香豆有N中写法。 构造函数设置成私有 静态构造方法构造对象。...

  • unity3d c#调用java

    c#调用java非静态方法 C#调用静态类,静态方法 ; CustomClass的静态类,SetData是它的静...

  • Unity面试刷题库

    C#问题 1.在类的构造函数前加上static会报什么错?为什么? 答:在构造函数如果有public修饰的静态构造...

网友评论

    本文标题:C#中为什么会出现空静态构造方法的写法

    本文链接:https://www.haomeiwen.com/subject/elcssqtx.html