您现在的位置: 天下网吧 >> 网吧天地 >> 天下码农 >> 微信小程序 >> 正文

加增对C# Static构造函数的认识

2010-12-22vczx佚名

     在学习 Design&Pattern 的 Singleton Pattern 的时候,因为静态初始化是在 .NET 中实现 Singleton 的首选方法.

public sealed class Singleton

{

static readonly Singleton instance = new Singleton();

static Singleton(){}

Singleton(){}

public static Singleton Instance

{

get{return instance;}

}

}

不过我对于 静态构造函数还是有点迷惑!它和实例化对象时的构造函数有什么区别,它们的关系又是什么呢?
查看了相关资料后现在对它有了一定的认识了!
静态成员的初始化语句会早于静态构造函数执行,其次静态构造函数是由CLR调用执行的,所以静态构造函数只能是一个,同时不能还有参数。那么静态构造函数相对于成员初始化的一些弊端都不复存在。
对于静态成员何时被初始化,静态构造函数又何时被调用,它们之间的先后顺序又是怎么样的呢?下面我们给出一个例子来说明一下!

using System;

namespace testStatic

{

class Program

{

static void Main(string[] args)

{

Console.WriteLine(A.X.ToString()); //Return: 2

Console.WriteLine(B.Y.ToString()); //Return: 1

Console.Read();

}

}

class A

{

public static int X = B.Y;

static A()

{

++X;

}

}

class B

{

public static int Y = A.X;

static B()

{

++Y;

}

}

}

说实话我在以前对于 static 的认识的基础上我真的不知道上面的会返回什么值!(做人得诚实,不懂不能装懂!呵呵...).其结果是“2,1”,也就是
A.X的值为2,
B.Y的值为1.
分析此类问题,只要记住三点就行了:
1. 代码的执行顺序,代码在前的先执行;
2. 静态成员初始化语句要先于静态构造函数执行;
3. 静态成员初始化语句与静态构造函数只执行一次。

如果了解这三点,接下来就分析为什么会出现上面的结果。
当调用到第一条语句的时候:
Console.WriteLine(A.X.ToString());
     首先是访问A这个类型,那么要对A这个类型的静态成员进行初始化,其次如果有静态构造函数,需要调用它。对于A的静态成员只有“X”,按照上一单元的过程,先给其分配空间,并辅以0来初始化,其次调用其对应的成员初始化语句来初始化这个静态成员。那么它的成员初始化语句是“X = B.Y”,那么需要访问“B.Y”来初始化X这个静态成员。
    对于“B.Y”的访问,就是访问B类型,也是和访问A一样,首先对这个类型的静态成员进行初始化,其次如果有静态构造函数,需要调用它。而B的静态成员只有“Y”,先给其分配空间,并辅以0来初始化,其次调用其对应的成员初始化语句来初始化这个静态成员。
    那么对于“Y = A.X”成员初始化语句,由于此时不是第一次访问类型A,所以不再进行静态成员初始化和静态构造函数的调用,对于“A.X”的访问是直接访问。此时“A.X”的值为0,那么Y的值也为0;接着执行B的静态构造函数,这样处理后Y的值为1。那么对于A中的成员初始化语句“X = B.Y”,到此就执行完了,此时A类型中的X与B类型中的Y都是一样的,值为1。不过B中的静态成员初始化语句和静态构造函数都执行过了,而A中的静态构造函数还未执行。因此经过A的静态构造函数处理,A的X值为2,这也就是最后显示的结果。

为了再加深一下对 Static 的印象,再个小的测试片断!这下就对 Static 印象更深了~~`

using System;

using System.Collections.Generic;

using System.Text;

using System.Threading;

namespace testStatic

{

class Program

{

static void Main(string[] args)

{

//Console.WriteLine(A.X.ToString());

//Console.WriteLine(B.Y.ToString());

A objA = A.Instance;

Console.WriteLine(objA.GetStr());

Console.Read();

}

}

class A

{

static A instance = null;

string str = "i am A, i am a member of class A";

public static int X = B.Y;

/**//// <summary>

/// 静态构造函数仅次于静态数据成员被调用.

/// </summary>

static A()

{

++X;

Console.WriteLine("hello A. I am from static A constructor");

}

private A()

{

Console.WriteLine("hello A. I am from private A constructor");

}

public string GetStr()

{

return str;

}

public static A Instance

{

get

{

//这里只有对类进行实例化的时候,非静态的构造函数才会被调用

return instance = new A();

}

}

}

class B

{

//静态成页最先被调用

public static int Y = A.X;

/**//// <summary>

/// 静态构造函数后于静态成员被调用

/// </summary>

static B()

{

++Y;

Console.WriteLine("hello B . I am from static B constructor");

}

/**//// <summary>

/// 只有对象被实例化的时候才会调用非静态构造函数

/// </summary>

private B()

{

Console.WriteLine("hello B . I am from private B constructor");

}

}

}

输出为:
hello B . I am from static B constructor
hello A. I am from static A constructor
hello A. I am from private A constructor
i am A, i am a member of class A
我头脑里搁不下疑问,有自己不明白的话就一门心思的想把它搞明白搞懂!想知道它是啥个回事~~``呵呵,明白了以后,心情很舒畅啊!!!!~~`

欢迎访问最专业的网吧论坛,无盘论坛,网吧经营,网咖管理,网吧专业论坛 https://bbs.txwb.com

关注天下网吧微信/下载天下网吧APP/天下网吧小程序,一起来超精彩

本文来源:vczx 作者:佚名

声明
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。若文章侵犯了您的相关权益,请及时与我们联系,我们会及时处理,感谢您对本站的支持!联系邮箱:support@txwb.com,系统开号,技术支持,服务联系QQ:1175525021本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧 网吧天下