当前位置:首页 > Web开发 > 正文

发现一个很有意思的东西

2024-03-31 Web开发

前几天在看书的时候看到一条内容 > 由于CLR保证一个类型结构器在每个AppDomain中只执行一次,而且(这种执行)是线程安适的,所以非常适合在类型结构器中初始化类型需要的任何单实例(Singleton)东西。
忽然想到,平时本身使用过程中都是通过Lazy来延迟化构建单例东西,就孕育产生了一个疑问,使用Lazy跟直接使用静态结构函数有什么区别,有什么优错误谬误呢?

颠末

抱着这个疑问,我查了一下相关的内容,发明一个很有意思的对象。
关于静态字段的初始化有两种写法

internal sealed class SomeType { ????private static Int32 s_x = 5; }

internal sealed class SomeType { ????private static Int32 s_x; ????static SomeType() ????{ ??????? s_x = 5; ????} }

我在网上所查到的内容是,在使用第一种要领初始化字段的时候,需要添加一个为空的静态结构函数,这样能够保证,该类型是在被用到的时候才去初始化该静态字段。否则,该类型的字段初始化会被提前,甚至可能由于这个不成控的提前导致一些奇怪的问题。但是这种写法也有一个问题,那就是别人可能认为这个空的静态结构函数是无用的而删除这一部分。所以本人认为,,下面这种写法更好一些(前提是.Net Framework)。

然后再来研究一下为什么会有这种奇怪的表示。这两种写法看起来没有什么区别,甚至于用JustDecomplie反编译dll出来的代码都是一致的。但是不雅察看生成的IL就会发明他们的区别,第一种写法生成的类会存在beforefieldinit标识表记标帜。由于编译器并不会供给默认的静态结构函数,所以在没有静态的时候,这个标识表记标帜会将字段的初始化提前,而这种提前是不成控的。当手动写了静态结构函数,无论结构函数内是否有内容,这个标识表记标帜城市被去失,从而促使字段的初始化只有在真正第一次使用到该类的时候才会执行。

本身的测验考试

看到这些对象之后,我也本身去做了一些测验考试,发明本身的测试项目跑起来并没有这些问题,甚至于字段的初始化还有延迟加载的特性,只有真正用到了这个字段的时候才去初始化这个字段。

思来想去想了很久,俄然发明本身的这个项目是一个.Net Core项目,难道说是.Net Core 与.Net Framework在这点的措置惩罚惩罚上有所差别?随后又去建了一个.Net Framework的项目,发明确实是存在提前初始化的情况。

两者存在差别这件事是可以确定的了,但是具体到底是怎么个差别呢?.Net Core 到底是如何措置惩罚惩罚beforefieldinit这个标识表记标帜的呢?

我随后又查了一些相关的内容加上本身做的一些测试,最后得出结论如下:

在存在静态结构函数的情况下,两者并没有什么区别,表示是一致的。

在不存在静态结构函数的情况下,也就是类存在beforefieldinit标签的情况下

.Net Framework 会将字段的初始化提前,并且不成控

而.Net Core 会做到延迟加载,只有当某一个字段真正被用到的时候,才会去初始化所有字段。所以在.Net Core中,是不是上面的第一种写法更好?终究有延迟加载的效果(虽然一个用到就会导致所有字段都初始化),固然关键还要看是否需要对字段初始化的时间精确控制,如果不需要精确控制,其实哪种写法都没差,这个视具体情况而定。

但是,我感受既然需要延迟加载,用Lazy来控制每个字段的延迟看起来可控性更高一些。

跋文

第一次写博客,有写的不同错误的处所还请见谅 (*^_^*)

.Net Framework 与 .Net Core中的静态结构函数

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/33063.html