.NET代码执行顺序探讨

简介:
    通常我们设计一个.NET应用程序,无需考虑过多就可以让我们的程序正确的跑起来。但是,当我们的设计日益复杂时,稍不小心就会因为不清楚.NET代码的执行顺序以及规则而使我们陷入困境。先来个小demo,检查一下你对它了解多少吧。
 1  public   class  MainTest
 2  {
 3       static   void  Main( string [] agrs)
 4      { // 断点①    (没错,是花括号)
 5          Console.WriteLine(Test1.Getddd()); // 断点②   (调用静态方法)
 6          Console.WriteLine(Test1.ddd); // 断点③   (调用静态字段)
 7      }
 8  };
 9  public   class  Test1
10  {
11       public   static   string  ddd  =  Test2.kkk; // 断点④
12       public   static   string  Getddd()
13      {
14           return   " ddd " ; // 断点⑤
15      }
16  };
17  public   class  Test2
18  {
19       public   static   string  kkk  =   " kkk " ; // 断点⑥
20  };
    
    问题一:上面的代码中,我定义了六个断点,你不妨思考一下,六个断点处的代码执行顺序如何。下面有两个观点,你认同哪个呢?
    观点1 : ① -- ⑤ -- ② -- ⑥ -- ④ -- ③
    观点2 : ⑥ -- ④ -- ① -- ⑤ -- ② -- ③
    (如果你还有其他观点,欢迎跟帖讨论)
    
    如果你支持观点1,那你就很值得把这篇文章一看了。如果你肯定观点2是正确的,那说明你已经出师,无需再看下文讲解。
    的确,观点2是正确。上面的代码主要的关键点有:
    1.函数中调用静态字段。
    2.函数中调用静态方法。
    3.类的静态字段中调用另一个类的静态字段。
    我们知道,类中的静态字段在整个程序中只会初始化一次,而静态方法却是每调用一次都要执行一次。
    
    问题二:我们的仅有一次的类中的静态字段是何时被初始化的呢?
    观点1 : 应用程序加载时就先把所有的静态字段都初始化一次。
    观点2 : 当第一次调用到某个静态字段的语句时才去初始化那个静态字段,并且把这个类中的其他静态字段也初始化。
    观点3 : 当第一次调用到某个静态字段的语句时才去初始化那个静态字段,并且只初始化这一个静态字段。
    
    又要做选择了,你选择哪个呢?答案是~~~~~~~~~~~都不对-_-!
    正确的初始化时机,我的理解是:当某个类第一次被实例化或类的静态方法第一次被调用或类的静态字段第一次准备要调用前,就尝试去初始化这个类的所有静态字段。为了验证这一点,我可以把上面的代码简单的修改一下:
 1  public   class  MainTest
 2  {
 3       static   void  Main( string [] agrs)
 4      { // 断点①    (没错,是花括号)
 5          Console.WriteLine(Test1.Getddd()); // 断点②   (测试调用静态方法时 类Test1中执行的顺序如何 )
 6           // Test1 t1 = new Test1();//断点③ (测试初始化类时类Test1中执行的顺序如何)
 7      }
 8  };
 9  public   class  Test1
10  {
11       public   static   string  ddd  =  "kkk"; // 断点④
12       public   static   string  Getddd()
13      {
14           return   " ddd " ; // 断点⑤
15      }
16  };
    
    我们可以看到,代码执行的顺序是:1 -- 4 -- 5 -- 2 。第一次调用了Test1.Getddd()方法时,就对静态字段ddd进行了初始化。我们可以修改代码,在Main函数里先实例化一个Test1,这时我们可以看到当实例化一个类的时候静态字段也被初始化了。
    
    问题三:为什么说上文说"类中的静态字段第一次准备要调用之前"?

    "准备要调用之前"指的是一个类中(如第一段代码中的Class Test1中执行初始化ddd时要调用到的Class Test2中的静态字段kkk)或是在一个函数体中(如第一段代码中Main函数体中将要调用的Class Test1中的静态字段ddd)中将要调用到某个类的静态字段时,编译器会首先检查到这一情况,最先将该静态字段所属的类中的所有的静态字段初始化,再开始执行类或函数中要执行的代码。这就说明了为什么第一段代码中没有先执行断点①而是先去初始化了那些静态字段。
    
    因此,总结如上,头脑中应该对于一个类、一个静态字段、一个静态方法、一个静态属性(执行顺序和静态方法几乎一样)、类中的构造函数等等的执行先后顺序有了比较清晰的了解。因此我个人总结了如下(希望批评指正):
    1.当一个类被实例化时,首先检查类中的静态字段是否已经初始化,如果没有初始化,将最先执行静态字段的初始化代码。(如果静态字段的初始化代码中又调用了另一个类中的静态字段,将最优先执行另一个类中的静态字段的初始化。)接着,将执行非静态字段的代码,然后再执行类的构造函数。
    2.当调用类的静态方法或属性时,也是首先检查类中的静态字段是否已经初始化,如果没有初始化,将最先执行静态字段的初始化代码。接着再执行静态方法或属性内部的代码。
    3.某个函数体中存在使用了某个类的静态字段时,无论静态字段在函数体的什么位置,只要这个静态字段没有被初始化,将优先于执行这个函数之前,执行该静态字段的初始化(实际上将该类中的所有静态字段都初始化了)。

    以上包含很多个人观点,有不对的地方希望大家批评指正!



本文转自CoderZh博客园博客,原文链接:http://www.cnblogs.com/coderzh/archive/2007/10/27/939702.html,如需转载请自行联系原作者

目录
相关文章
|
前端开发 程序员 C#
【C#】.net core2.1,在实体类写了个非常经典的无限循环错误
遇到一个非常有趣的bug,使用VS2017调试运行.net core2.1 MVC项目时,程序本身运行的好好的,突然启动起来就报错 不得不说,编码细节很重要
113 0
|
.NET Windows
理解“.NET技术”.NET程序集的执行过程
  对于一个已编译好的.NET程序集,Windows操作系统是如何启动执行的呢?日常使用中我们发现对于托管的和非托管的程序集编译器都会吧程序集编译成以.exe或.dll等为扩展名的文件,可见Windows加载器并没有区分是托管还是非托管的程序集,而且我们也知道对非托管的程序集是在编译器直接编译成了机器码,自然可以由CPU直接执行,而托管的.
821 0
|
.NET Windows
一起谈.NET技术,理解.NET程序集的执行过程
  对于一个已编译好的.NET程序集,Windows操作系统是如何启动执行的呢?日常使用中我们发现对于托管的和非托管的程序集编译器都会吧程序集编译成以.exe或.dll等为扩展名的文件,可见Windows加载器并没有区分是托管还是非托管的程序集,而且我们也知道对非托管的程序集是在编译器直接编译成了机器码,自然可以由CPU直接执行,而托管的.
709 0
|
程序员
一起谈.NET技术,不要在using语句中调用WCF服务
  如果你调用WCF服务时,像下面的代码这样在using语句中进行调用,需要注意一个问题。 using (CnblogsWcfClient client = new CnblogsWcfClient()){ client.Say("Hello, cnblogs.com!");}   上面这段代码看上去没问题,CnblogsWcfClient是一个自动生成的WCF客户端代理,继承自System.ServiceModel.ClientBase。
717 0
|
安全
.NET Core中延迟单例另一种写法【.NET Core和.NET Framework的beforefieldinit差异】
1.BeforeFieldInit是什么    前段时间在反编译代码时无意间看到在类中有一个BeforeFieldInit特性,处于好奇的心态查了查这个特性,发现这是一个关于字段初始化时间的特性【提前初始化字段】,下面先来看一下这个特性在.
1779 0
|
C# 编译器 Python
动态执行 VB.NET 和 C# 代码
原文:动态执行 VB.NET 和 C# 代码 有时候我们需要尝试动态地与一些代码进行交互,而不是只能执行程序内已编死的代码,那该怎么办呢?我首先推荐各种脚本语言,如Javascript、Lua、Python等等,这些脚本语言有很多优秀的第三方类库,可以很方便的与 .NET 系统集成,让我们的程序中执行动态代码。
1322 0

热门文章

最新文章