CLR保证一个类型构造器在每个AppDomain中只执行一次,而且这种执行是线程安全的。

作用:

就是初始化静态成员

比如有几个静态成员需要初始化
那你把初始化代码放到哪呢?

放到普通构造函数里,那肯定不行。因为静态成员没有创建实例就要可用。

专门建一个static public方法来初始化?这样用起来非常不方便,你需要在“第一次”使用静态成员前先调用这个方法。
如果你在使用静态成员前忘了调用该方法,会导致错误。
如果重复调用,又是冗繁操作。

所以静态构造函数就派上用场了。
它会在你第一次调用静态成员(或创建实例)的时候自动被调用

解析:

静态构造器函数是实现对一个类进行初始化的方法成员,它一般用于对静态数据的初始化。静态构造函数不能有参数,不能有修饰符而且不能被调用,当类被加载时,类的静态构造器自动被调用。

在一个程序的执行过程中,静态构造器最多只执行一次。

静态构造器在类的静态成员初始化之后执行,或者讲编译器会将静态成员初始化语句转化成赋值语句放在静态构造器执行的最开始。

静态构造器在任何类的静态成员被引用之前执行。

静态构造器在任何类的实例变量被分配之前执行。

静态构造器最主要的作用是对类的静态成员进行初始化。

namespace 静态构造器
{
class A
{
public static int i = ;
static A() //静态构造器能不能带参数,不能有修饰符,默认private
{
Console.WriteLine("我是类A的静态构造器");
} public A()
{
Console.WriteLine("我是类A的无参构造器");
}
} //编译之后等价于
//class A
//{
// public static int i ;
// static A() //静态构造器能不能带参数,不能有修饰符,默认private
// {
// i = 100;
// Console.WriteLine("我是类A的静态构造器");
// } // public A()
// {
// Console.WriteLine("我是类A的无参构造器");
// }
//} class Program
{
static void Main(string[] args)
{
Console.WriteLine(A.i);//当类被加载时,类的静态构造函数自动被调用,静态构造器是在a被使用前加载的 // A a = new A(); //静态构造器最多只执行一次 Console.ReadKey();
}
}
}

最近看书,看到静态构造函数的时候,发现其不能从程序中显示调用,而通常静态构造函数初始化类的静态字段,这样的话,为何不直接在静态字段定义的时候直接为其赋值呢?

直接赋值的结果就是它们会被放到静态构造函数中执行.

和一般的构造函数类似的呀,赋值只是构造函数的一个功能。有时候,你需要在静态构造函数中写一些逻辑,或是执比一些代码,比如工厂模式中很多的,要读取配置文件,然后把根据配置的文件初使化一些常用的对象,比如单例模式中的唯一对象,或者spring中的session什么的。反正一句话是,有些逻辑也要放在构造函数中,静态的也是。

先看代码:

1.包含静态字段的调用

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Console.WriteLine("EntryPoint");
  6. Console.WriteLine(StaticClass.staticMem);
  7. StaticClass.ShowStaticStr("Call Static Method");
  8. Console.Read();
  9. }
  10. class StaticClass
  11. {
  12. public static string staticMem = ShowStaticStr ("Static Member");
  13. public static string ShowStaticStr(string message)
  14. {
  15. Console.WriteLine(message);
  16. return message;
  17. }
  18. }
  19. }
    class Program
{
static void Main(string[] args)
{
Console.WriteLine("EntryPoint");
Console.WriteLine(StaticClass.staticMem);
StaticClass.ShowStaticStr("Call Static Method");
Console.Read();
} class StaticClass
{
public static string staticMem = ShowStaticStr ("Static Member");
public static string ShowStaticStr(string message)
{
Console.WriteLine(message);
return message;
}
}
}

结果如下:

添加静态构造函数:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Console.WriteLine("EntryPoint");
  6. Console.WriteLine(StaticClass.staticMem);
  7. StaticClass.ShowStaticStr("Call Static Method");
  8. Console.Read();
  9. }
  10. class StaticClass
  11. {
  12. public static string staticMem = ShowStaticStr("Static Member");
  13. public static string ShowStaticStr(string message)
  14. {
  15. Console.WriteLine(message);
  16. return message;
  17. }
  18. static StaticClass()
  19. { }
  20. }
 class Program
{
static void Main(string[] args)
{
Console.WriteLine("EntryPoint");
Console.WriteLine(StaticClass.staticMem);
StaticClass.ShowStaticStr("Call Static Method");
Console.Read();
} class StaticClass
{
public static string staticMem = ShowStaticStr("Static Member");
public static string ShowStaticStr(string message)
{
Console.WriteLine(message);
return message;
} static StaticClass()
{ }
}

结果如下:

2.去掉静态字段调用

  1. static void Main(string[] args)
  2. {
  3. Console.WriteLine("EntryPoint");
  4. // Console.WriteLine(StaticClass.staticMem);
  5. StaticClass.ShowStaticStr("Call Static Method");
  6. Console.Read();
  7. }
  8. class StaticClass
  9. {
  10. public static string staticMem = ShowStaticStr ("Static Member");
  11. public static string ShowStaticStr(string message)
  12. {
  13. Console.WriteLine(message);
  14. return message;
  15. }
  16. }
 static void Main(string[] args)
{
Console.WriteLine("EntryPoint");
// Console.WriteLine(StaticClass.staticMem);
StaticClass.ShowStaticStr("Call Static Method");
Console.Read();
} class StaticClass
{
public static string staticMem = ShowStaticStr ("Static Member");
public static string ShowStaticStr(string message)
{
Console.WriteLine(message);
return message;
}
}

结果如下:

添加静态构造函数:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Console.WriteLine("EntryPoint");
  6. //Console.WriteLine(StaticClass.staticMem);
  7. StaticClass.ShowStaticStr("Call Static Method");
  8. Console.Read();
  9. }
  10. class StaticClass
  11. {
  12. public static string staticMem = ShowStaticStr("Static Member");
  13. public static string ShowStaticStr(string message)
  14. {
  15. Console.WriteLine(message);
  16. return message;
  17. }
  18. static StaticClass()
  19. { }
  20. }
class Program
{
static void Main(string[] args)
{
Console.WriteLine("EntryPoint");
//Console.WriteLine(StaticClass.staticMem);
StaticClass.ShowStaticStr("Call Static Method");
Console.Read();
} class StaticClass
{
public static string staticMem = ShowStaticStr("Static Member");
public static string ShowStaticStr(string message)
{
Console.WriteLine(message);
return message;
} static StaticClass()
{ }
}

结果如下:

显式定义静态构造函数时的IL:

未显式定义静态构造函数的IL:

未显式定义静态构造函数时,IL中多了一个beforefieldinit标志,此标志使得运行库能够在任何时候执行类型构造函数方法,只要该方法(静态构造函数)在第一次访问该类型的静态字段(而不是方法)之前执行即可。换句话说,beforefieldinit 为运行库提供了一个执行主动优化的许可。如果没有 beforefieldinit,运行库就必须在某个精确时间(调用之前)运行类型构造函数,即,恰好在第一次访问该类型的静态或实例字段和方法之前。当存在显式类型构造函数时,编译器不会用 beforefieldinit 标记该类型,精确的计时限制会导致 FxCop 所暗示的性能下降。

6 CLR静态构造器的更多相关文章

  1. 静态构造器(static constructor)

    1.定义: 静态构造函数是实现对一个类进行初始化的方法成员. 它一般用于对静态数据的初始化. 静态构造函数不能有参数,不能有修饰符而且不能被调用,当类被加载时,类的静态构造函数自动被调用. 2.特点: ...

  2. Clr静态数据Table-Valued函数

    前两天Insus.NET实现一个功能<在数据库中提供只读数据>http://www.cnblogs.com/insus/p/4384411.html ,在数据库中为程序提供静态数据.它是在 ...

  3. 6 CLR实例构造器

    引用类型构造器 如果我们没有定义实例构造器,那么编译器会为我们默认产生一个无参构造器. 实例对象初始化过程 为实例分配内存: 初始化附加成员,包括方法表指针和SyncBlockIndex变量(我们已经 ...

  4. CLR类型设计之方法与构造器

    无论学习那门语言都要学习函数体,C#,JAVA,PHP,都会涉及到函数体,而C#的函数体成员并不少,方法和构造器就是函数体成员之一,函数体成员还包括但不限于:方法,属性,构造器,终结器,运算符及索引器 ...

  5. 《CLR.via.C#第三版》第二部分第12章节 泛型 读书笔记(六)

    终于讲到泛型了.当初看到这个书名,最想看的就是作者对泛型,委托,反射这些概念的理解.很多人对泛型的理解停留在泛型集合上,刚开始我也是,随着项目越做越多,对待泛型的认识也越来越深刻. 泛型的概念:泛型是 ...

  6. c# 变量,对象,静态类型,集合类的线程安全回顾

    1.变量的线程安全性与变量的作用域有关. 2.对象 对象是类型的实例 在创建对象时,会单独有内存区域存储对象的属性和方法.所以,一个类型的多个实例,在执行时,只要没有静态变量的参与,应该都是线程安全的 ...

  7. CLR via C#(05)- 访问限定、数据成员

    今天跟大家分享一下关于访问限定和数据成员的知识.主要包括以下两点: Abstract, sealed, virtual, new, override怎么用? Const 和 readonly好像都表示 ...

  8. CLR via C#学习笔记----知识总概括

    第1章 CLR的执行模型 托管模块的各个组成部分:PE32或PE32+头,CLR头,元数据,IL(中间语言)代码. 高级语言通常只公开了CLR的所有功能的一个子集.然而,IL汇编语言允许开发人员访问C ...

  9. CLR 初步

    1. 源代码编译为托管模块 程序在.NET框架下运行,首先要将源代码编译为 托管模块.CLR是一个可以被多种语言所使用的运行时,它的很多特性可以用于所有面向它的开发语言.微软开发了多种语言的编译器,编 ...

随机推荐

  1. Android真机测试、乐视手机启用开发者模式

    一.乐视手机启用开发者模式 1.进入 设置>关于手机,连续按5次,进入开发者模式 显示结果如下: 2.启用开发者模式,并且要启用USB调试 3.在VS中部署或调试Android引用,使用真机测试 ...

  2. C# Round源码

    在日常开发中经常遇到四舍五入的情况比如 Math.Round(1.25, 1),首先我们要知道这里的Round 其实是银行家算法,具体可以参考Round() 四舍五入 js银行家算法 那么C#是如何实 ...

  3. chapter15中使用generator来实现异步化操作的同步化表达的例子

    在p203中作者给了一个例子,我感觉这个例子写的不好,一开始我没有看懂,因为中间有很多细节没有交代,直到看了第二个用generator来实现ajax的例子之后才有所领悟.   所以我把作者给的这个用g ...

  4. [Canvas]Bombman v1.04

    Bombman是我仿造红白机上经典游戏爆破小人,用Canvas制作的一款网页版单机游戏, 自我感觉还是有一定的可玩性. 本游戏的胜利条件是用雷消灭所有怪物,但被怪物即使是擦边碰到或是炸弹火焰炸到就算失 ...

  5. 浅谈压缩感知(二十四):压缩感知重构算法之子空间追踪(SP)

    主要内容: SP的算法流程 SP的MATLAB实现 一维信号的实验与结果 测量数M与重构成功概率关系的实验与结果 SP与CoSaMP的性能比较 一.SP的算法流程 压缩采样匹配追踪(CoSaMP)与子 ...

  6. Flume采集Nginx日志到HDFS

    下载apache-flume-1.7.0-bin.tar.gz,用 tar -zxvf 解压,在/etc/profile文件中增加设置: export FLUME_HOME=/opt/apache-f ...

  7. 阿里云的免费型DV SSL证书

    阿里云提供的免费型DV SSL. 证书的说明: [公告]免费新根证书,切入DigiCert PKI体系,兼容性如下操作系统版本IOS 5.0+.Android 2.3.3+.JRE 1.6.5+.WI ...

  8. tmux手册中文翻译

    man tmux可以看到最详细的tmux介绍,本文翻译自tmux手册. tmux全名叫"terminal multiplexer",终端多路复用器. tmux的命令格式为: tmu ...

  9. windows下vbs脚本隐藏控制台

    每次想写python代码时,都需要打开IDE进行编写,并且需要创建许多小文件.如果使用jupyter就能够直接书写.但是jupyter需要手动通过控制台打开,这不够方便.通过把jupyter note ...

  10. [AaronYang]那天有个小孩跟我说Js-NodeJS[AY0]-EJS

    按照自己的思路学习Node.Js 随心出发.EJS是Node.js中express框架中使用的一个模版引擎,当然还有Jade 我的学习就靠网上查资料,没有买书系统学,自己整理,如果有用了哪位大神的代码 ...