扯下闲篇先,本来今天预计整理下委托、事件、Lamada的笔记,然后再把单例模式的懒汉、饿汉模式看完。

在看到懒汉的双重加锁设计时,向同桌贩卖了下该设计的优点,结果反被同桌的一个问题难倒了~!

一. 有无静态构造方法,运行结果大不同

问题:请问下面代码的运行结果是什么?

 using System;

 namespace FirstTest
{
class A
{
public static string name = GetName ("Hello World~!"); public static string GetName (string str)
{
Console.WriteLine("初始化静态成员:{0}", str);
return str;
}
} class Program
{
static void Main(string[] args)
{
Console.WriteLine ("输出第一句话");
string temp = A.name;
Console.WriteLine("输出静态成员:{0}", temp);
}
}
}

一开始,我认为是:1)输出第一句话 2)初始化静态成员 3)输出静态成员

运行结果:

结果出乎意料吧?

为什么静态成员的初始化反而先于第一句话执行呢??

正在我百思不得其解的时候,同桌在原代码的基础上稍加改动,又发给了我:

 using System;

 namespace FirstTest
{
class A
{
public static string name = GetName ("Hello World~!"); public static string GetName (string str)
{
Console.WriteLine("初始化静态成员:{0}", str);
return str;
} // 在A类中增加其静态构造方法
static A ()
{
}
} class Program
{
static void Main(string[] args)
{
Console.WriteLine ("输出第一句话");
string temp = A.name;
Console.WriteLine("输出静态成员:{0}", temp);
}
}
}

这一次,运行结果和我刚刚预期的结果反而一致了。

运行结果:

为什么A类中有无静态构造方法,会对运行结果造成如此影响?

在对度娘上的博客进行各种遍历搜索查询之后,终于捋清了如下思路:

  1. 前后两段代码的异同点,仅局限于A类中有无静态构造方法。在缺少静态构造方法的情况下(即第一种情况),运行结果“异常”(不符合预期结果)。
  2. 在缺少静态构造方法的情况下,程序会自动生成默认静态构造方法

由以上两点推测,较为认同如下观点:

  • 编译器在编译的时候,会事先分析Main方法中所需要的静态字段
  • 如果这些静态字段所在的类有静态构造函数,则只有在初次引用该字段(或初次实例化类)的时候才进行初始化
  • 否则,在调用Main方法前,自动生成静态构造方法,对静态字段进行初始化

继续码代码:增加一个class B,在Main方法中分别调用A、B的静态字段,印证观点:

 using System;

 namespace FirstTest
{
class A
{
public static string name = GetName("Hello World~!"); public static string GetName(string str)
{
Console.WriteLine("初始化静态成员:{0}", str);
return str;
} // 在A类中增加其静态构造方法
static A()
{
}
}
class B
{
public static string name = GetName("Learning C#"); public static string GetName(string str)
{
Console.WriteLine("初始化静态成员:{0}", str);
return str;
} // B类中缺少静态构造方法,将由系统自动生成
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("开始执行Main方法");
// 首先引用A类的静态字段
string first = A.name;
// 其次引用B类的静态字段
string second = B.name;
}
}
}

按照观点分析:1)初始化静态成员:Learning C# 2)开始执行Main方法 3)初始化执行静态成员:Hello World~!

运行结果:

与观点分析的预期相符,结题。

参考博文:

《浅谈静态字段与静态构造函数之间的初始化关系以及执行顺序》

作者:Rain

http://www.cnblogs.com/cpcpc/archive/2010/04/16/2123135.html

二. 静态构造方法与静态字段的执行顺序

在查阅上个问题的过程中,发现在MSDN上对静态构造方法的描述中有如下一条内容:

如果类包含任何带有初始值设定项的静态字段,则在执行该类的静态构造函数时,先要按照文本顺序执行那些初始值设定项

观点主要阐述了以下3点:

  • 执行静态构造方法时,先对静态字段进行初始化,然后再调用静态构造方法里面的内容
  • 对静态字段进行初始化时,按照静态字段声明的依次顺序进行
  • 若静态字段含有初始值含有初始值设定项,则使用设定项。否则对其使用默认值,值类型的默认值为0(其中布尔类型为false),引用类型的默认值为null。

本着打破砂锅问到底的精神,仅在A类中添加如下两行静态字段,在静态构造函数中添加一行输出语句,进行测试:

 class A
{
public static string front = GetName("前排强势占座!!!!");
public static string name = GetName("Hello World~!");
public static string back = GetName("后排无聊围观...."); public static string GetName(string str)
{
Console.WriteLine("初始化静态成员:{0}", str);
return str;
} // 在静态构造方法增加输出语句
static A()
{
Console.WriteLine("调用静态构造方法");
}
}

按照MSDN的观点:1)初始化静态成员:Learning C# 2)开始执行Main方法 3)初始化执行静态成员:前排强势占座!!!! 4)初始化执行静态成员:Hello World~! 5)初始化执行静态成员:后排无聊围观.... 6)调用静态构造方法

运行结果:

与观点分析的预期相符,新姿势Get√

另外,根据MSDN中的静态构造函数设计中的描述,CLR可以优化对静态字段进行初始值设定项的代码。

三. 静态构造方法与Main方法的执行顺序

同样的,在MSDN中发现如下观点:

如果类中包含用来开始执行的 Main 方法,则该类的静态构造函数将在调用 Main 方法之前执行。

重写一份代码(含有静态构造方法),再次实验下:

 using System;

 namespace FourthText
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine ("这是最后一个试验了~\\(≧▽≦)/~啦啦啦");
} static Program()
{
Console.WriteLine ("调用静态构造方法");
}
}
}

运行结果:

与观点分析的预期相符,新姿势Get√

啊啊啊啊O(≧口≦)O,还不能结题~!结合第一、二条知识,再次测试下没有静态构造方法下的情况吧:

 using System;

 namespace FourthText
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("真的是最后一次试验了Zzz");
} public static string name = GetName("又被骗了(#‵′)凸"); public static string GetName(string str)
{
Console.WriteLine("初始化静态成员:{0}", str);
return str;
}
}
}

运行结果:

【C#】静态构造方法与静态变量的更多相关文章

  1. C#中为什么会出现空静态构造方法的写法

    再过几个小时,就要回家过春节了,今天说些简单点的东西,大家在看C#代码的时候,一定会对这样的写法非常迷茫:在一个类中会出现一个空的静态构造方法.这不是多此一举吗,这样做的目的是什么?今天我就来说说这个 ...

  2. Java类的初始化顺序 (静态变量、静态初始化块、变量、初始...

    很有意思的一篇文章 1.没有继承 静态变量->静态初始化块->变量->变量初始化块->构造方法 2.有继承的情况 父类静态变量->父类静态初始化块->子类静态变量- ...

  3. java静态代码块/静态属性、构造块、构造方法执行、main方法、普通代码块的顺序

    java静态代码块/静态属性.构造块.构造方法执行.main方法.普通代码块的顺序 这也是在笔试中的一个重要的考点,就有一个输出语句让你写出输出的结果. 理论知识: 静态代码块是:属于类的,在类加载时 ...

  4. DotNet中静态成员、静态类、静态构造方法和实例构造方法的区别与联系

    在面向对象的C#程序设计中,关于静态的概念一直是很多人搞不明白的.下面介绍这些带“静态”的名称. 1.静态成员: 定义:静态成员是用static关键字修饰的成员(包括字段属性和方法) 所属:静态成员是 ...

  5. 静态局部变量、静态全局变量、extern全局变量、自动变量 札记

    静态局部变量 静态局部变量. 从称呼上我们可以看出,静态局部变量首先是一个局部变量,因此其只在定义它的函数内有效,冠以静态的头衔后,其生存期就被延长了,不会随着函数的返回而被撤销.我们可以这样来理解: ...

  6. 1、c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

    1.c#中可以有静态构造方法,而java中没有,例如在单例模式中c#可以直接在静态构造中实例化对象,而java不可以

  7. Java 构造器 考虑用静态构造方法代替构造器

    类可以提供一个公有的静态工厂方法,它是一个返回类的实例的静态方法.静态工厂方法与设计模式中的工厂方法模式不同. 优势: 静态工厂方法与构造器不同的第一大优势在于,它们有名称.一个类只能有一个带有指定签 ...

  8. C# 静态构造函数,静态变量执行顺序(精华版)(规正版)

    一.成员初始化整体顺序 1.成员赋值初始化先于构造函数: 2.成员赋值初始先从子类再到基类: 3.构造函数初始化先从基类再到子类: 4.静态成员初始化优先于实例成员初始化: 二.对类型静态成员构造的大 ...

  9. Objective-C之成魔之路【9-类构造方法和成员变量作用域、以及变量】

    郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 构造方法 ...

随机推荐

  1. java验证工具类(待验证)

    /** * <判断对象是否为null或者空> * * @param obj * 需要判断的对象 * @return 如果对象为null或者空则返回true */ public static ...

  2. SpringBoot常用配置,引入外部配置文件信息,热加载

    SpringBoot的配置文件格式 yml规范 SpringBoot的配置文件支持properties和yml,甚至还支持json. 更推荐使用yml文件格式: yml文件,会根据换行和缩进帮助咱们管 ...

  3. 06 大数据CentOS6.5mini安装与网络配置

    1. CentOS6.5mini安装 文件>>新建虚拟机 选择自定义,下一步 默认,下一步 选择稍后安装操作系统,下一步 选择CentOS版本,下一步 给虚拟机命名,这个是在VMWare中 ...

  4. 2020-07-08:mysql只有一个表a,什么情况下会造成死锁,解决办法是什么?

    福哥答案2020-07-08: 表锁是不会出现死锁的,但锁等待现象是有可能的.行锁是行级别的,有可能出现死锁.环形等待死锁和唯一键死锁 很常见. 避免死锁方法:1.减少事务操作的记录数.2.约定按相同 ...

  5. C#图解教程(第四版)—02—类的基本概念

    类  是一种能 存储数据  并且  执行代码  的数据结构,他包含数据成员和函数成员 .成员可以是9种可能的成员类型的任意组合 字段 属性 方法 常量 构造函数 析构函数 运算符 索引器 事件 1 字 ...

  6. 数据源管理 | 分布式NoSQL系统,Cassandra集群管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.Cassandra简介 1.基础描述 Cassandra是一套开源分布式NoSQL数据库系统.它最初由Facebook开发,用于储存收件箱 ...

  7. 关于Dapper实现读写分离的个人思考

    概念相关     为了确保多线上环境数据库的稳定性和可用性,大部分情况下都使用了双机热备的技术.一般是一个主库+一个从库或者多个从库的结构,从库的数据来自于主库的同步.在此基础上我们可以通过数据库反向 ...

  8. python设计模式之代理模

    python设计模式之代理模式 在某些应用中,我们想要在访问某个对象之前执行一个或多个重要的操作,例如,访问敏感信息--在允许用户访问敏感信息之前,我们希望确保用户具备足够的权限.操作系统中也存在类似 ...

  9. MySQL服务操作

    启动: systemctl start mysqld.service; 状态: systemctl status mysqld.service; 重启: systemctl restart mysql ...

  10. kafka-clients 1.0 高阶API消费消息(未完)

    消费消息的请求(按序) org/apache/kafka/common/requests/RequestHeader org/apache/kafka/common/requests/ApiVersi ...