beforefieldinit释义
首先让我们认识什么是,当字段被标记为beforefieldinit类型时,该字段初始化可以发生在任何时候任何字段被引用之前。这句话听起了有点别扭,接下来让我们通过具体的例子介绍。
/// <summary>
/// Defines a test class.
/// </summary>
class Test
{
public static string x = EchoAndReturn("In type initializer"); public static string EchoAndReturn(string s)
{
Console.WriteLine(s);
return s;
}
}
上面我们定义了一个包含静态字段和方法的类Test,但要注意我们并没有定义静态的构造函数。

图3 Test类的IL代码
class Test
{
public static string x = EchoAndReturn("In type initializer"); // Defines a parameterless constructor.
static Test()
{
} public static string EchoAndReturn(string s)
{
Console.WriteLine(s);
return s;
}
}
上面我们给Test类添加一个静态的构造函数。

图4 Test类的IL代码
通过上面Test类的IL代码的区别我们发现,当Test类包含静态字段,而且没有定义静态的构造函数时,该类会被标记为beforefieldinit。
现在也许有人会问:“被标记为beforefieldinit和没有标记的有什么区别呢”?OK现在让我们通过下面的具体例子看一下它们的区别吧!
class Test
{
public static string x = EchoAndReturn("In type initializer"); static Test()
{
} public static string EchoAndReturn(string s)
{
Console.WriteLine(s);
return s;
}
} class Driver
{
public static void Main()
{
Console.WriteLine("Starting Main");
// Invoke a static method on Test
Test.EchoAndReturn("Echo!");
Console.WriteLine("After echo");
Console.ReadLine(); // The output result:
// Starting Main
// In type initializer
// Echo!
// After echo
}
}
我相信大家都可以得到答案,如果在调用EchoAndReturn()方法之前,需要完成静态成员的初始化,所以最终的输出结果如下:

图5输出结果
接着我们在Main()方法中添加string y = Test.x,如下:
public static void Main()
{
Console.WriteLine("Starting Main");
// Invoke a static method on Test
Test.EchoAndReturn("Echo!");
Console.WriteLine("After echo"); //Reference a static field in Test
string y = Test.x;
//Use the value just to avoid compiler cleverness
if (y != null)
{
Console.WriteLine("After field access");
}
Console.ReadKey(); // The output result:
// In type initializer
// Starting Main
// Echo!
// After echo
// After field access }

图6 输出结果
通过上面的输出结果,大家可以发现静态字段的初始化跑到了静态方法调用之前,Wo难以想象啊!
最后我们在Test类中添加一个静态构造函数如下:
class Test
{
public static string x = EchoAndReturn("In type initializer"); static Test()
{
} public static string EchoAndReturn(string s)
{
Console.WriteLine(s);
return s;
}
}

图7 输出结果
理论上,type initializer应该发生在”Starting Main”之后和”Echo!”之前”,但这里却出现了不唯一的结果,只有当Test类包含静态构造函数时,才能确保type initializer的初始化发生在”Starting Main”之后和”Echo!”之前”。
所以说要确保type initializer发生在被字段引用时,我们应该给该类添加静态构造函数。
beforefieldinit释义的更多相关文章
- beforefieldinit释义(3)
1.看下面的例子: public static class MyClass<T> { public static readonly DateTime Time = GetNow(); pr ...
- beforefieldinit释义(2)
首先来看一段代码: using System; namespace BeforeFieldInit { internal class Foo { Foo(){ Console.WriteLine(&q ...
- 常见linux命令释义(第八天)—— Bash Shell 的操作环境
换了新公司,公司的领导很不错.自己感受比较多的地方是,自己的工作效率明显比以前高了.以前会对频繁变动的需求十分不耐烦,现在接到需求后会仔细的思考,进行整体构建.即使以后需求有变动,也能够比较轻易的在原 ...
- 常见linux命令释义(第三天)
今天晚上看鸟哥的私房菜,边学边写笔记. 在linux中压缩大多是.tar, .tar.gz , .tgz, /gz, .bz2等. .gz 是通过gzip压缩的文件. .bz2 是通过bzip2压缩的 ...
- 常见linux命令释义(第一天)
快到中午吃饭了,然后忽然想起来samba里面没有添加用户.于是乎,就玩弄起了samba. Samba三下五除二就安装好了,想想window里面不断的点击下一步,还要小心提防各种隐藏再角落里的绑定软件. ...
- Tomcat的目录结构、处理流程、主配置文件(server.xml)释义
参考资料: http://www.cnblogs.com/xdp-gacl/p/3744053.html http://grass51.blog.51cto.com/4356355/1123400 1 ...
- 使用Perl5获取有道词典释义
Get Word Definition from dict.youda.com via Perl Script 获取基本释义 Get Basic Definition http://dict.youd ...
- Web前端名词释义及原理
引言:看题目的时候,不要觉得这是一个很深奥的问题,Web前端这些东西很多就是叫的名字牛逼,其实原理很TM简单,也就那么回事. 一.javascript名词释义 1.啥是事件队列? 就是 弄一个数组,里 ...
- linux内核的冒险md来源释义# 14raid5非条块读
linux内核的冒险md来源释义# 14raid5非条块读 转载请注明出处:http://blog.csdn.net/liumangxiong 假设是非条块内读.那么就至少涉及到两个条块的读,这就须要 ...
随机推荐
- idea maven 无法加载已经安装的模块
新建了一下maven项目,下面新建了一个模块,某一个模块clean install之后,别的模块虽然使用dependency标签引入了,但是仍然无法使用, 这个时候,应该重新建立一个项目,将原有项目的 ...
- centos7命令行与图形界面启动模式修改
1.命令启动 systemctl set-default multi-user.target 2.图形界面模式 systemctl set-default graphical.target
- gridview获取当前行索引的方法
在用GridView控件时,我们经常会碰到获取当前行的索引,通过索引进行许多操作.例如,可以获得当前行某一个控件元素:设置某一元素的值等等. 下面结合实例介绍几种获得GridView当前行索引值的方法 ...
- 常用网站开发类Firefox扩展插件 (转)
作为一个 Web 开发人员,你几乎没有理由不喜欢Firefox,因为在Firefox下有很多专门针对开发的扩展插件,非常好用,这里就介绍一些常用的针对网站开发的FireFox扩展,供Web开发人员参考 ...
- shopnc 发票项目
---恢复内容开始--- file_put_contents( 't.txt' , print_r($input_invoice_info ,true) ); 打印 $input_invoice_in ...
- PHP基础温习之echo print printf sprintf print_r var_dump的用法与区别
一.echoecho() 实际上不是一个函数,是php语句,因此您无需对其使用括号.不过,如果您希望向 echo() 传递一个以上的参数,那么使用括号会发生解析错误.而且echo是返回void的,并不 ...
- Python之路第七天,基础(9)-面向对象(上)
面向对象的编程思想 回想 我们所学过的编程方法: 面向过程:根据业务逻辑从上到下写堆叠代码. 函数式编程:将重复的代码封装到函数中,只需要写一遍,之后仅调用函数即可. 面向过程编程最易被初学者接受,其 ...
- 'ManyRelatedManager' object is not iterable
先看下面的代码: class Worker(models.Model): departments = moels.ManyToManyField(Department, verbose_name=u& ...
- Android manifest
manifest是Android应用程序的配置文,在这里指定了改程序的资源.权限等内容,一般的manifest文件如下 <manifest xmlns:android="http:// ...
- Java Web 中 过滤器与拦截器的区别
过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法u ...