zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    微软外服 AlI In One
    js 循环多次和循环一次的时间的性能对比 All In One
    vue inject All In One
    Excel 表格数据倒置 All In One
    SVG tickets All In One
    OH MY ZSH All In One
    js array for loop performance compare All In One
    mac terminal show You have new mail All In one
    新闻视频 26 制作母版页
    转自牛腩 母版页和相对路径
  • 原文地址:https://www.cnblogs.com/wwkk/p/10321776.html
Copyright © 2011-2022 走看看