发现一段很诡异的C#代码,见识了静态构造函数这种奇怪的东西:

  1. using System;
  2. namespace StaticTest
  3. {
  4. class A
  5. {
  6. public static int X;
  7. static A()
  8. {
  9. X = B.Y + 1;
  10. }
  11. }
  12. class B
  13. {
  14. public static int Y = A.X + 1;
  15. static B()
  16. {
  17. }
  18. static void Main()
  19. {
  20. Console.WriteLine("X={0}, Y={1}", A.X, B.Y);
  21. }
  22. }
  23. }

先补习下吧:

  1、静态构造函数既没有访问修饰符,也没有参数。因为是.NET调用的,所以像public和private等修饰符就没有意义了。 
   
  2、是在创建第一个类实例或任何静态成员被引用时,.NET将自动调用静态构造函数来初始化类,也就是说我们无法直接调用静态构造函数,也就无法控制什么时候执行静态构造函数了。

  3、一个类只能有一个静态构造函数。

  4、无参数的构造函数可以与静态构造函数共存。尽管参数列表相同,但一个属于类,一个属于实例,所以不会冲突。

  5、最多只运行一次。

  6、静态构造函数不可以被继承。

  7、如果没有写静态构造函数,而类中包含带有初始值设定的静态成员,那么编译器会自动生成默认的静态构造函数。

好,复习完毕,哪位同学回答下上面程序的输出结果是多少?

还是搞不明白吧:) 唔,你明白了?他没明白,我也没明白……

class A静态构造函数中的B.Y好像很奇怪,貌似要确定A.X的值,得先确定B.Y的值,而B.Y的值在B中却是由A.X来确定的,那A.X的值……啊,要疯掉了……应该是多少呢?不敢确定了吧,交给编译器来运行看看吧~~ 
结果如下:

  1. X=1, Y=2

修改下代码,看看内部到底怎么运行的:

  1. using System;
  2. namespace StaticTest
  3. {
  4. class A
  5. {
  6. public static int X;
  7. static A()
  8. {
  9. Console.WriteLine("calling A");
  10. Console.WriteLine(B.Y);
  11. X = B.Y + 1;
  12. }
  13. }
  14. class B
  15. {
  16. public static int Y = A.X + 1;
  17. static B()
  18. {
  19. Console.WriteLine("calling B");
  20. Console.WriteLine(Y);
  21. }
  22. static void Main()
  23. {
  24. Console.WriteLine("X={0}, Y={1}", A.X, B.Y);
  25. }
  26. }
  27. }

执行结果如下:

  1. calling A
  2. 0
  3. calling B
  4. 2
  5. X=1, Y=2

看到这个结果,对C#更加迷惑了。类A中静态构造函数调用得到的B.Y,居然是0。这是什么道理?难道这个时候B还没出生,但是B.Y已经出生了?不管了,先接受了吧,以后玩C#还是小心点了。哪位神仙指点指点迷津啊?

说说C#静态变量的诡异与恶心的更多相关文章

  1. PHP 面向对象编程和设计模式 (2/5) - 静态变量、属性和方法及延迟绑定

    PHP高级程序设计 学习笔记 2014.06.10 Static(静态)关键字用来定义静态方法和属性,static 也可用于定义静态变量以及后期静态绑定. 1.静态变量 static variable ...

  2. [转]Android静态变量的生命周期

    原文地址:https://my.oschina.net/jerikc/blog/137207 Android是用Java开发,其静态变量的生命周期遵守Java的设计.我们知道静态变量是在类被load的 ...

  3. QT,静态变量要记得初始化

    //DbUtil.h #ifndef DBUTIL_H #define DBUTIL_H using namespace std; QString md5Encode(QString passwd); ...

  4. .NET静态变量与静态方法并发的问题

    我们知道,静态变量与静态方法都是在程序编译的时候就定义好了的,并且不会存在多个副本.所以对于静态变量来说,一旦修改了就会影响全局. 因此,静态变量是存在并发性问题的,所以当我们在操作静态变量的时候需要 ...

  5. JAVA的静态变量、静态方法、静态类

    静态变量和静态方法都属于静态对象,它与非静态对象的差别需要做个说明. (1)Java静态对象和非静态对象有什么区别? 比对如下: 静态对象                                ...

  6. 关于C#静态变量初始化问题

    关于这个静态变量,平时自己没有太认真的去认识.最近调项目的bug,让我重新认识了静态变量的特点. 其实,我们一直都在说:静态变量只在类第一次初始化的时候进行初始化,以后都不初始化. 很简单的一句话,但 ...

  7. android 尽量不要使用static静态变量

    使用静态static静态变量潜在性问题: 1.占用内存,并且内存一般不会释放: 2.在系统不够内存情况下会自动回收静态内存,这样就会引起访问全局静态错误. 3.不能将activity作为static静 ...

  8. Java代码执行顺序(静态变量,非静态变量,静态代码块,代码块,构造函数)加载顺序

    //据说这是一道阿里巴巴面试题,先以这道题为例分析下 public class Text { public static int k = 0; public static Text t1 = new ...

  9. Java---类加载机制,构造方法,静态变量,(静态)代码块,父类,变量加载顺序

    直接上代码: 代码1: public class ConstroctTest { private static ConstroctTest test = new ConstroctTest(); // ...

随机推荐

  1. 讲解HTML服务器推送相关技术知识(转)

    1. 为什么需要服务器推送? 最大的优点:实时 健康知识平台重庆男科医院 重庆妇科医院适用场景:实时股票价格.商品价格.实时新闻.Twitter/weibo timeline.基于浏览器的聊天系统 2 ...

  2. JS方式调用本地的可执行文件

    看到一个方法,有些用,先存下来,有用的时候再用. 前几天,在IE,FIREFOX中实现了用JS方式调用本地的可执行文件.地址:www.yihaomen.com/article/js/211.htm , ...

  3. python中的深拷贝与浅拷贝

    深拷贝和浅拷贝 浅拷贝的时候,修改原来的对象,浅拷贝的对象不会发生改变. 1.对象的赋值 对象的赋值实际上是对象之间的引用:当创建一个对象,然后将这个对象赋值给另外一个变量的时候,python并没有拷 ...

  4. fopen警告处理方式

    warning C4996: “fopen”被声明为否决的 问题:vs2005中编程时,遇到如下: warning C4996: “fopen”被声明为否决的. 解释:微软的警告,主要是那些都是C库的 ...

  5. Protocol Buffer详解

    1.Protocol Buffer 概念 Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 ...

  6. mysql cluster 名词概念解读

    Node Group [number_of_node_groups] = number_of_data_nodes / NoOfReplicas Partition When using ndbd, ...

  7. 让CSS3给你的文字加上边框宽度,并实现镂空效果

    这次,我主要向大家介绍一下CSS3下的-webkit-text-stroke属性,并分享几个用该属性制作的镂空文字效果. 1.-webkit-text-stroke属性简介 CSS边框的一个不足就是只 ...

  8. HDU 5867 Water problem (模拟)

    Water problem 题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5867 Description If the numbers ...

  9. vim之grep

    [vim之grep] :vimgrep 用于多文件搜索,如 1):vim[grep] start_stage *   在当前目录下(不包括子目录)搜索 2)  :vim[grep] start_sta ...

  10. C++11对象构造的改良

    [C++11对象构造的改良] C++03中一个构造函数无法构造另一个构造函数,因为A()实际上意味着生成一个临时对象,存在语音混淆.详情请看参考2. C++11中允许直接在初始化列表中调用其它的构造函 ...