扯下闲篇先,本来今天预计整理下委托、事件、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. 微信小程序--家庭记账小账本(三)

    家庭记账小账本打算先通过微信小程序来实现,昨天就去注册了解了一下微信小程序,感觉比较复杂而且困难.如何将ecplise源代码与小程序连接,如何建立数据库等等都困扰了我.查阅网上的资料也没有很大的进展. ...

  2. layui 事件监听触发

    1:监听select 改变 <!-- 不用form 用div也可以 --> <form class="layui-form"> <div class= ...

  3. Take C# 8.0 for a spin

    本文章为机器翻译.https://blogs.msdn.microsoft.com/dotnet/2018/12/05/take-c-8-0-for-a-spin/ 以C # 8兜风 我们昨天宣布Vi ...

  4. C#LeetCode刷题之#189-旋转数组(Rotate Array)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3700 访问. 给定一个数组,将数组中的元素向右移动 k 个位置, ...

  5. C#LeetCode刷题之#561-数组拆分 I(Array Partition I)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3718 访问. 给定长度为 2n 的数组, 你的任务是将这些数分成 ...

  6. Vue 过滤器 Filter传递参数

    给日期类型过滤器设置不同格式 dayjs是一款轻量级的日期操作库 https://day.js.org/en import Vue from 'vue' import dayjs from 'dayj ...

  7. Flutter 容器(7) - DecoratedBox

    DecoratedBox: 装饰容器,在其子widget绘制前(或后)绘制一个装饰Decoration(如背景.边框.渐变等) import 'package:flutter/material.dar ...

  8. 文件上传控件bootstrap-fileinput中文设置没有效果的情况

    1.引入zh.js顺序错误 zh.js需放到fileinput.js下面 2. 组件创建语法错误 (class=“file”) 如果你使用js初始化fileinput组件,那么在html元素中应删除 ...

  9. 简单快速导出word文档

    最近,我写公司项目word导出功能,应该只有2小时的工作量,却被硬生生的拉长2天,项目上线到业务正常运行也被拉长到2个星期. 为什么如此浪费时间呢? 1)公司的项目比较老,采用硬编码模式,意味着wor ...

  10. 学习java的第五周

    java流程控制 顺序结构 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执的处理步骤组成的,它是任何-一个算法都离不开的一种基本算法结构. 选择结构 if结构 if(布尔表达式 ...