.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,如需转载请自行联系原作者

目录
相关文章
|
JSON IDE 前端开发
[.NET开发者的福音]一个方便易用的在线.NET代码编辑工具.NET Fiddle
[.NET开发者的福音]一个方便易用的在线.NET代码编辑工具.NET Fiddle
126 0
|
开发框架 JavaScript 前端开发
震撼!破解 ASP.NET 服务器控件 Button 执行顺序之谜,颠覆你的开发认知!
【8月更文挑战第16天】在ASP.NET开发中,通过Button控件实现先执行JavaScript再触后台处理的需求十分常见。例如,在用户点击按钮前需前端验证或提示,确保操作无误后再传递数据至后台深度处理。此过程可通过设置Button的`OnClientClick`属性调用自定义JavaScript函数完成验证;若验证通过,则继续触发后台事件。此外,结合jQuery也能达到相同效果,利用`__doPostBack`手动触发服务器端事件。这种方式增强了应用的交互性和用户体验。
127 8
【Azure 媒体服务】Media Service的编码示例 -- 创建缩略图子画面的.NET代码调试问题
【Azure 媒体服务】Media Service的编码示例 -- 创建缩略图子画面的.NET代码调试问题
|
C# 开发者 Windows
在VB.NET项目中使用C#编写的代码
在VB.NET项目中使用C#编写的代码
153 0
|
9月前
|
算法 Java 测试技术
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
使用 BenchmarkDotNet 对 .NET 代码进行性能基准测试
209 13
|
9月前
|
开发框架 .NET PHP
ASP.NET Web Pages - 添加 Razor 代码
ASP.NET Web Pages 使用 Razor 标记添加服务器端代码,支持 C# 和 Visual Basic。Razor 语法简洁易学,类似于 ASP 和 PHP。例如,在网页中加入 `@DateTime.Now` 可以实时显示当前时间。
|
10月前
|
敏捷开发 缓存 中间件
.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素
本文深入探讨了.NET技术的高效开发模式,涵盖面向对象编程、良好架构设计及高效代码编写与管理三大关键要素,并通过企业级应用和Web应用开发的实践案例,展示了如何在实际项目中应用这些模式,旨在为开发者提供有益的参考和指导。
104 3
|
11月前
|
前端开发 JavaScript C#
CodeMaid:一款基于.NET开发的Visual Studio代码简化和整理实用插件
CodeMaid:一款基于.NET开发的Visual Studio代码简化和整理实用插件
237 0
【Azure Key Vault】.NET 代码如何访问中国区的Key Vault中的机密信息(Get/Set Secret)
【Azure Key Vault】.NET 代码如何访问中国区的Key Vault中的机密信息(Get/Set Secret)