博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BeforeFieldInit的小叙
阅读量:4317 次
发布时间:2019-06-06

本文共 2946 字,大约阅读时间需要 9 分钟。

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

你可能感兴趣的文章
数学基础 数论(二)
查看>>
走进模块
查看>>
什么是簇?
查看>>
[LeetCode] Construct Binary Tree from Inorder and Pretorder Traversal
查看>>
[转载]Android通过Socket上传文件
查看>>
golang 中的定时器(timer),更巧妙的处理timeout
查看>>
AT2134 Zigzag MST
查看>>
[NOI2019]回家路线
查看>>
何谓CRT,CRT的由来
查看>>
项目管理实践--VisualSVN Server
查看>>
2595 X之于Y 思维
查看>>
Selenium Webdriver模拟鼠标键盘操作
查看>>
java 导入其他包_java - 如何从默认包导入类
查看>>
嵌入式和java哪个难学_嵌入式和java哪个前景好
查看>>
java即时通讯 开源_im即时通讯开源
查看>>
kettle java交互_通过Java调取Kettle的结果集
查看>>
mysql 导致iis 假死_解决IIS无响应假死状态
查看>>
mysql数据库读取快照隔离_CookBook/1-MySQL数据库读写锁示例详解、事务隔离级别示例详解.md at master · cuiko/CookBook · GitHub...
查看>>
skinme java 路径错误_java 错误 classes路径配置错误
查看>>
python安装tensorflow gpu_[tensorflow] tensorflow-cpu/gpu 安装过程
查看>>