扯下闲篇先,本来今天预计整理下委托、事件、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. Chrome太占内存?试试这个

    " The Great Suspender" 是一个免费的开源 Google Chrome 扩展程序,适用于那些发现chrome占用过多系统资源或经常遭受chrome崩溃的人. 一 ...

  2. Python爬取招聘网站数据,给学习、求职一点参考

    1.项目背景 随着科技的飞速发展,数据呈现爆发式的增长,任何人都摆脱不了与数据打交道,社会对于“数据”方面的人才需求也在不断增大.因此了解当下企业究竟需要招聘什么样的人才?需要什么样的技能?不管是对于 ...

  3. 高级搜索树-伸展树(Splay Tree)

    目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...

  4. 基于 Docker 搭建 Consul 多数据中心集群

    本文介绍了在 Windows 10 上基于 Docker 搭建 Consul 多数据中心集群的步骤,包括 Consul 镜像的拉取和容器的创建,每个数据中心对应服务端节点和客户节点的创建,节点之间相互 ...

  5. scss @mixin & @include

    定义一个带参数和默认值的mixin class // demo.scss @mixin button($background:#606266) { font-size: 1em; padding: 0 ...

  6. jquery—实现能滚动的选项卡效果

    选项卡在网页中很常见,可以说是必备的一个元素了,网上其实也有很多案例讲解选项卡的做法,写这篇文章,就是记录下自己的写一个的实例效果图: html: css样式: 主要是滚动条的的样式设置width:1 ...

  7. 洛谷P1308.统计单词数(字符串匹配)

    题目描述 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数. 现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给 ...

  8. 关于python中Enum的个人总结

    关于python中Enum的个人总结 初识 可以通过enum模块导入 语法 初始化: 可以通过enum_ = Enum('class_name', names,start = 1)来创建,其中name ...

  9. 在K3s上使用Kong网关插件,开启K3s的无限可能!

    我的工作中很重要的一部分是参加各种各样的技术会议.最近参加的是去年11月的北美KubeCon,在会议的最后一天,所有人都焦头烂额,我也一直机械地向不同的人重复我的自我介绍.后来,我已经十分烦躁,决定逃 ...

  10. Dotnet Core Public API的安全实践

    公开API的安全,其实更重要.   一.API的安全 作为一个Dotnet Core的老司机,写API时,能兼顾到API的安全,这是一种优雅.   通常,我们会用认证来保证API的安全,无敌的Auth ...