再过几个小时,就要回家过春节了,今天说些简单点的东西,大家在看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方法 配置中心的内容,但是,当我们运行:



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

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

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

输出竟然被改变了。

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

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



IL代码有一个标记:beforefieldinit

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



beforefieldinit标记消失了。

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

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

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

C#中为什么会出现空静态构造方法的写法的更多相关文章

  1. DotNet中静态成员、静态类、静态构造方法和实例构造方法的区别与联系

    在面向对象的C#程序设计中,关于静态的概念一直是很多人搞不明白的.下面介绍这些带“静态”的名称. 1.静态成员: 定义:静态成员是用static关键字修饰的成员(包括字段属性和方法) 所属:静态成员是 ...

  2. 1、c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

    1.c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

  3. Java中什么是匿名对象,空参构造方法输出创建了几个匿名对象,属性声明成static

    package com.swift; //使用无参构造方法自动生成对象,序号不断自增 public class Person { private static int count; //如果在定义类时 ...

  4. PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化)/约束类型/魔术方法小结

      前  言  OOP  学习了好久的PHP,今天来总结一下PHP中的抽象类与抽象方法/静态属性和静态方法/PHP中的单利模式(单态模式)/串行化与反串行化(序列化与反序列化). 1  PHP中的抽象 ...

  5. Java 构造器 考虑用静态构造方法代替构造器

    类可以提供一个公有的静态工厂方法,它是一个返回类的实例的静态方法.静态工厂方法与设计模式中的工厂方法模式不同. 优势: 静态工厂方法与构造器不同的第一大优势在于,它们有名称.一个类只能有一个带有指定签 ...

  6. 【C#】静态构造方法与静态变量

    扯下闲篇先,本来今天预计整理下委托.事件.Lamada的笔记,然后再把单例模式的懒汉.饿汉模式看完. 在看到懒汉的双重加锁设计时,向同桌贩卖了下该设计的优点,结果反被同桌的一个问题难倒了~! 一. 有 ...

  7. Linux中的动态库和静态库(.a/.la/.so/.o)

    Linux中的动态库和静态库(.a/.la/.so/.o) Linux中的动态库和静态库(.a/.la/.so/.o) C/C++程序编译的过程 .o文件(目标文件) 创建atoi.o 使用atoi. ...

  8. 在seajs中使用require加载静态文件的问题

    注意,在seajs中使用require加载静态文件时,必须使用常量,不能用变量.如果一定要用变量,请使用require.async var html = require("view/sys/ ...

  9. C语言中全局变量、局部变量、静态全局变量、静态局部变量的区别 (转)

    1.C++变量根据定义的位置的不同的生命周期,具有不同的作用域,作用域可分为6种: 全局作用域,局部作用域,语句作用域,类作用域,命名空间作用域和文件作用域. 从作用域看: 1>全局变量具有全局 ...

随机推荐

  1. Android Studio编译卡死

    首先,用AS,你必须fanqiang,其它都是次要的. AS/bin/*.exe.vmoptions ## *DO NOT* modify this file directly. If there i ...

  2. FreeBSD 与中文

    $ setenv LC_ALL en_US.UTF- 然后用 locale 检查 en_US 不是重点,重点是 UTF-8 . 然后用 putty,原因是默认终端又没有中文字体...然后就能输入输出中 ...

  3. 使用云服务器实现Google搜索

    >>>>>>>>>>>>>>>>>>>>>>>>> ...

  4. Imcash:一边大裁员,一边大扩招,你能否成为区块链人才中的7%?

    农历春节后,互联网创业圈并不太平. 最早,滴滴被曝裁员,占比约为全员的15%,涉及员工约2000人.CEO程维在全员会议上称公司要做好过冬准备.此后,京东接棒,其裁员对象上升至副总裁级别高管,比例占到 ...

  5. Lightscape

    Lightscape是一种先进的光照模拟和可视化设计系统,用于对三维模型进行精确的光照模拟和灵活方便的可视化设计. Lightscape是一个光照渲染软件,它特有的光能传递计算方式和材质属性所产生的独 ...

  6. BZOJ5335 : [TJOI2018]智力竞赛

    二分答案,转化成求最少的路径,覆盖住所有权值$\leq mid$的点. 建立二分图,若$i$的后继为$j$,则连边$i\rightarrow j$,求出最大匹配,则点数减去最大匹配数即为最少需要的路径 ...

  7. 关于H5的一些杂思细想(一)

    作为一名前端程序媛,虽然整天和代码打交道,但是还是有一颗小清新的内心,虽然有时候加起班来不是人,但是空闲的时候还是会整理一下思绪,顺便整理一下自己,两个多月的加班,一直没有更新,今天就把自己最近做的一 ...

  8. WinccFlexible 同一个项目创建多个connections

    在一个WinccFlexible 项目中,可以创建多个通讯连接,以满足不同的接口要求. 但是需要在控制面板上 Set PG/PC Interface中添加新的连接,并绑定对应的网卡即可.

  9. sql server创建登录出发器后导致登录失败--解决方案

    1.选择sql server配置管理器---sql server服务--右键属性--启动参数--添加-f.-m两个参数并重启sql server服务 2.重新启动sql server以windos身份 ...

  10. 暴力求解Calculator:The Game

    本文详实的记录的我的思考过程,类似流水账.... 目前已经烂尾,我对付不了133关后面的关卡 这个手机游戏挺不错的,就是有点难,所以要写程序,暴力的通关. 游戏名字:Calculator:The Ga ...