BeforeFieldInit的小叙

BeforeFieldInit是什么

上片的文章中我们看到了有静态构造函数,和没有静态构造函数,代码的执行顺序有着显著的区别。然后,我们反编译了下代码,发现了在类中有一个BeforeFieldInit特性,通过查各处资料,发现这是一个关于字段初始化时间的特性【提前初始化字段】,下面先来看一下这个特性在.net framework中的作用。摘取了别人的一份Demo:

class Foo
{
   public static String x = GetStr("初始化 Foo 静态成员字段");
   public static String GetStr(String str)
  {
       Console.WriteLine(str);
       return str;
  }
}

在上面Foo类中只定义了一个静态字段x和一个静态方法GetStr的方法,在这里需要关注的是静态字段x的初始化时机

static void Main(string[] args)
{
      Console.WriteLine("Main方法开始");
      Foo.GetStr("手动调用Foo.GetSring()方法");
      String y = Foo.x;
}

运行的结果如下:

可以看到静态成员字段的初始化是在最开始,我们将代码反编译IL后会发现在类中具有一个beforefieldinit特性

.class private auto ansi beforefieldinit BeoreFieldInitTest2.Foo
    extends [mscorlib]System.Object
{
} // end of class BeoreFieldInitTest2.Foo

这里是对beforefieldinit的一个介绍 点我

如果想要取消BeofreFieldInit的话,可以显式的写静态构造函数

class Foo
{
     public static string x = GetStr("初始化 Foo 静态成员字段");
     //空的静态构造函数
     static Foo(){}
     public static String GetStr(String str)
     {
         Console.WriteLine(str);
          return str;
      }
}

  

结果如下:

反编译可以看到IL代码也取消了beforefieldinit特性

.class private auto ansi BeoreFieldInitTest2.Foo
    extends [mscorlib]System.Object
{
} // end of class BeoreFieldInitTest2.Foo

正如 别的园友告知,.NET Core中却有不一样的BeforeFieldInit

将最开始的代码在.NET Core中跑一跑会发现跟.NET Framework不一样的操作

可以看到在.NET Core并没有像.NET Framework那样进行提前加载,并且加载貌似还延迟了,而且,反编译代码可以看到beforefieldinit特性还在Foo类上。

那么在.NET Core加入静态构造函数?

可以看到.NET Core中加入静态构造函数以后输出跟.NET Framework一致

在.NET Framework中我们都是使用Lazy<>类来创建延迟加载单例,但是我们可以看到在.NET Core中beforefieldinit是延迟加载的,所以我们直接可以使用此方法来创建延迟安全单例

class Program
{
    static void Main(string[] args)
    {
         Console.WriteLine("Main方法开始");
         Foo.GetStr("手动调用Foo.GetSring()方法");
         Console.WriteLine("我是分隔符");
          Console.WriteLine("我是分隔符");
          var foo= Foo.CreateInstance;
     }
}
class Foo
{
     public static Foo CreateInstance { get;  } = new Foo();
     private Foo()
     {
         Console.WriteLine("创建了Foo实例");
     }
     public static String GetStr(String str)
     {
         Console.WriteLine(str);
         return str;
     }
 }

运行结果可以看到创建实例被延迟了

当然,这种创建单例也是有缺点的,当类中还有其它静态字段或属性时,并且在外部进行了调用,那么此时也会初始化此属性

class Program
{
     static void Main(string[] args)
     {
         Console.WriteLine("Main方法开始");
         Foo.GetStr("手动调用Foo.GetSring()方法");
         var y = Foo.x;//调用静态字段/属性
         Console.WriteLine("我是分隔符");
         Console.WriteLine("我是分隔符");
         var foo= Foo.CreateInstance;
     }
 }
 class Foo
 {
     public static string x = GetStr("初始化 Foo 静态成员字段"); //加入了静态字段或属性
     //public static String X { get; set; } = GetStr("初始化 Foo 静态成员字段");
     public static Foo CreateInstance { get;  } = new Foo();
     private Foo()
     {
         Console.WriteLine("创建了Foo实例");
     }
     public static String GetStr(String str)
     {
         Console.WriteLine(str);
         return str;
     }
}

也就是说在.NET Core中beforfieldinit特性时当有一个静态变量被使用时就初始化所有静态变量

参考:https://www.cnblogs.com/yan7/p/9187874.html

原文地址:https://www.cnblogs.com/wwkk/p/10321776.html

时间: 2024-10-18 15:22:55

BeforeFieldInit的小叙的相关文章

《java入门第一季》之类(String类常见方法小叙)

String类下面的构造方法和一些常见的方法: /* * 字符串:就是由多个字符组成的一串数据.也可以看成是一个字符数组. * 通过查看API,可以知道 * A:字符串字面值"abc"也可以看成是一个字符串对象. * B:字符串是常量,一旦被赋值,就不能被改变. * * 构造方法: * public String():空构造 * public String(byte[] bytes):把字节数组转成字符串 * public String(byte[] bytes,int index,i

小叙Spring.NET(Ioc与DI)的使用步骤

那今天就介绍一下我理解的Spring.net吧.介绍Spring.NET之前,先谈点其他的.我们都知道,.NET有一个基本原则"高内聚,低耦合".关于这个概念,想必大家都知道.所谓高内聚,也就是模块内部内聚,各个模块之间"低耦合".也就是结耦,降低耦合度.所以我们选取了传统的三层,把,数据访问层,业务逻辑层,UI层分离,降低耦合度!       但是这还不够,我们为了让业务逻辑层与数据访问层彻底结耦.可以用面向接口编程的思想,采用抽象工厂模式.也就是建立工厂,采用映

时间正则表达式小叙

yyyy-MM-dd HH:mm:ss 正则表达式如下: ^((((1[6-9]|[2-9]\d)\d{2})-(0?[13578]|1[02])-(0?[1-9]|[12]\d|3[01]))|(((1[6-9]|[2-9]\d)\d{2})-(0?[13456789]|1[012])-(0?[1-9]|[12]\d|30))|(((1[6-9]|[2-9]\d)\d{2})-0?2-(0?[1-9]|1\d|2[0-8]))|(((1[6-9]|[2-9]\d)(0[48]|[2468][0

cacti小叙

cacti是用php语言实现的一个软件,它的主要功能是用snmp服务获取数 据,然后用rrdtool储存 和更新数据,当用户需要查看数据的时候用rrdtool生成图表呈现给用户. 一.概述 1. cacti是用php语言实现的一个软件,它的主要功能是用snmp服务获取数据,然后用rrdtool储存和更新数据,当用户需要查看数据的时候用 rrdtool生成图表呈现给用户.因此,snmp和rrdtool是cacti的关键.Snmp关系着数据的收集,rrdtool关系着数据存储和图表 的生成. 2.

yum小叙

yum全称为yellow dog updatemodifier ,基于rpm包管理,完美的解决了安装程序时各程序之间的依赖关系,也就是类似于windows中的一键安装,它可以从指定的本地路径或服务器自动下载rpm包并且安装,于此来说yum作为升级版rpm着实给我们带来了更便捷的操作体验. 但是yum这个命令需要有一些支持,因为我们安装的程序包是需要有来源的,就好似在windows下安装程序需要先从网上下载下来程序包,或者说本地有此程序包,才能使用yum命令来安装此包,所以说,使用yum命令的前提

Linux运维工作经验小叙

个人认为一个运维人员最应该的一天工作时间安排: 40%,处理紧急重要的事情:60%,开展重要不紧急的工作.紧急重要很容易理解,其实就是救活类工作.重要不紧急的工作,才是最能体现运维价值的工作. 监控系统,这是一个大话题.除了被动地监控各类服务的正常工作与否,还有主动开发协助系统分析的系统,并对整个系统的未来有规划性的开发工具型系统.提高自己和团队内所有人的工作效率的一些工具,尤其是可以快速解决那些中断的工具. 学习,这个是最重要的.运维涉及到的知识面非常广,不断学习才能顺利快速解决工作中出现的种

MOSFET使用与H桥驱动问题

0.小叙闲言 最开始学习三极管的时候,很注重它的工作原理,后来到了实际应用,就直接把三极管或MOSFET直接当作一个开关器件使用.直到前这几天,接触到MOSFET组成的H桥驱动电路时,发现把它纯当作一个开关器件来看,会出现许多问题.在这里总一下问题和对出现问题的一些原因做一些分析.个人知识有限,很多地方思虑难免有所不足,希望能够与网上各位一起学习交流. 目前我们一般将H桥驱动当作电机或步进电机的驱动,如下图1所示,要做好驱动电路,必须得了解清楚MOSFET的一些原理,才不会出错.  图1 H桥全

利用卷积网络识别骰子点数

前言小叙 前一段时间通过bpnn反向传播神经网络实现了识别骰子点数的目标,而且效果不错,我们的识别率可以达到80%上下,其实已经可以应用于生产环境了.只不过读了卷积神经网络,第一次感受到原来还可以这样,感受到了新的世界观和人生观. 卷积这个词,第一次接触还是读图形处理的书的时候,中间会有卷积和滤波处理图片的内容,其实当时对于卷积也是懵懵懂懂,不明所以,无非就是一个个求积再求和,能有什么意义.不过这些天我算是有些明白了. 想通俗了解卷积的朋友可以访问这个链接.境外的朋友请看YouTube短视频,下

PPT制作线条动画

0.小叙闲言 今天在用PPT做动画的时候小有心得,百度了一下线条动画制作,有一个贴子里面的讨论,也给了我一些灵感,贴子地址:http://www.rapidbbs.cn/thread-24577-1-1.html.但是还是没有做下图这样的效果的动画,这是自己纯想出来的,分享一下,或许对大家有点帮助.文章中的PPT下载地址:http://files.cnblogs.com/files/endlesscoding/PPT_Line_Animations.zip 1.PPT简单线条动画 平时做线条动画