静态构造函数与静态变量

静态构造函数

http://tech.ddvip.com/2009-02/1235012605109159.html


refer to : http://space.itpub.net/12639172/viewspace-462842

C# 对象初始化

1.     先变量后构造函数。变量先被初始化 ,然后构造函数被执行

2.     先静态化后实例化。 一个类被访问时 ,静态变量和构造函数最先被初始化 .接着是对象的实例化变量和构造函数被初始化

3.     先派生类后基类。对于变量和静态构造函数 ,派生对象在基对象之前被初始化 .比如 C类派生自 B ,B类派生自 A ,那么变量和静态构造函数被初始化次序是 C-B-A.

4.     除了实例构造函数。对于实例构造函数 ,基类构造函数在派生类构造函数之前执行 ,实例构造函数被执行次序是 A-B-C.

5.     不要假定变量的次序。 Fields依据它们在源文件中的声明的顺序依次初始化 .然而 ,自从程序员 和工具可以随意安排变量的声明后 ,你不应该在依靠变量任何特别的次序初始化

6.     对虚方法用两个阶段的构建。避免从一个构造器调用虚方法 .如果在初始化一个对象时需要调用一些虚方法 ,应在完整构造该对象的地方使用两阶段的构建,并随后调用已构造对象的初始化方法。


refer to : http://blog.sina.com.cn/s/blog_55100f7901000c6i.html

先来看一个经典题目:
class A
    {
        public static int X;
        static A()
        {
            X = B.Y + 1;
        }
    }
    class B
    {
        public static int Y = A.X + 1;
        static B() { }
        static void Main()
        {
            Console.WriteLine("X={0},Y={1}", A.X, B.Y);
        }
    }
问的是输出的结果是什么,也就是Main()里面 A.X, B.Y的值
这个题目的答案是 1,2
为什么呢?
因为执行的时候,首先从程序的入口点 (就是Main())找起,因为Main在类B中,所以从B类开始加载。执行顺序大致是这样的:
(用到一个类的时候是先对其静态变量初始化,然后调用他的静态构造函数)
(类的静态构造函数只在加载类的时候由系统调用一次且只此一次)
1.初始化B类的静态变量 Y ,系统先给他一个默认值 (此处是0 ),然后再执行他的初始化赋值语句 public static int Y = A.X + 1;
2.执行这条语句的时候因为用到了A.X,所以遇到A的时候去加载类A ,顺序一样,先是执行A的静态变量X 的初始化工作public static int X;因为没有对其赋值的操作,所以X就是系统给他的默认值0 ;然后调用A的静态构造函数 (B那里也是先初始化静态变量,然后才调用静态构造函数,因为B初始化静态变量的时候用到了A所以才会跳到A来,不然的话B那边也是初始化静态变量之后系统紧接着就会调用B的静态构造函数);

3,A的静态构造函数中执行X = B.Y + 1;可以知道,此时B.Y已经有了一个系统给他的默认值0,所以此处就是X=0+1;现在X就是1了
4,X那边都完工了,回到刚才跳转X的地方继续执行,就是继续 执行Y = A.X + 1;毫无疑问此时是Y=1+1;至此,B的静态变量初始化完成 了。
5,B的静态变量初始化完成了那紧接着就是系统调用B的静态构造函数 ,此处什么也不执行。
6.输出结果1,2
 
总结一下:
1、这种东西总归就是执行的时候,Main在哪个类里面就先初始化哪个类(如果Main在外边,比如Main不在A,B中,那么看Main先用到谁就先初始化谁 );
2、然后初始化的时候,在加载类的时候是先初始化类的静态变量,然后接着执行类的静态构造函数(静态构造函数是加载类的时候系统调用的,只执行这一次。);
3、初始化静态变量的时候,系统先给他赋上默认值,然后才执行类中定义的赋值语句,比如public static int  Z = 3;实际上是先是Z=0;然后Z=3;
4、初始化完了静态变量之后紧接着调用此类的静态构造函数(上面的那个例子也是按照这个顺序的,有人可能问为什么上面那个例子B静态变量初始化的时候有跳 转,其实那也是完全按照顺序执行,因为B顺序是现初始化静态变量,然后静态构造函数。可是B静态变量初始化的时候用到了A,那A就也是静态变量-构造函 数,然后回到B静态变量初始化的语句继续执行,B静态变量初始化完了才紧接着B静态构造函数。)
5、看看下面几个例子,全都做对了就说明你掌握了

using System;
    class A
    {
        public static int X;
        static A()
        {
            X = B.Y + 1;
        }
        static void Main(string[] args)
        {
            Console.WriteLine("A.X:{0}/tB.Y:{1}", A.X, B.Y);
            Console.Read();
        }
    }
    class B
    {
        public static int Y = A.X + 1;

        static B();
        {
        }
    }

上面这个例子的结果是什么呢???

他的执行顺序应该是

1、public static int X;

2、static A(){X = B.Y + 1;}

3、public static int Y = A.X + 1;

4、static B();

没错,结果就是 2,1

再看下面的一个

using System;
    class A
    {
        public static int X;
        static A()
        {
            X = B.Y + 1;
        }

    }
    class B
    {
        public static int Y = A.X + 1;

        static B();
        {
        }
    }

      class C

      {

              static void Main(string[] args)
 
            {
 
                    Console.WriteLine("A.X:{0}/tB.Y:{1}", A.X, B.Y);
 
                    Console.Read();
 
            }

        }

结果是什么呢?

他的执行顺序应该是

1、public static int X;

2、static A(){X = B.Y + 1;}

3、public static int Y = A.X + 1;

4、static B();

没错,结果还是 2,1,因为先用到的A后用到的B嘛!

 


refer to :http://www.soidc.net/articles/1213781277395/20060906/1214037779788_1.html

 

  分析此类问题,只要记住三点就行了。
  
  第一代码的执行顺序,代码在前的先执行;

  第二静态成员初始化语句要先于静态构造函数执行;

  第三静态成员初始化语句与静态构造函数只执行一次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值