6、正儿八经说Static
(看到圈里的骂声越来越多了,虽然言论自由,可是还是删掉了一些让我看完以后站起来喘大气的评论。之前写了那么多,对话的内容要比技术的内容多很多,但是也是一种Q&A的的方式,我觉得这样很好理解,毕竟如果让已经开发多年的人看这个文章,肯定会感觉弱智低级。就像现在看婴儿读物一样,可是要让涉世未深的孩子看起来,那就是最好的老师。有人说这是误导,其实不然,这是引导,有多少年来人们都以为在月球上面看中国,长城是唯一看的清楚的东西呢?可是只有真正的宇航员才知道,这只不过是树立民族自豪感的一种方式而已,哪能看见什么长城。再说哪本书没个ABC啊,所以,要是觉得这些文章让你恶心、反胃、吃不下饭、流口水、神志不清,请赶快ALT+F4,谢谢。这篇就不以对话的形式来写了。)
6.1 静态数据
之前的内容已经提到了静态方法。在JAVA中被静态修饰过的成员依然可以通过实例来调用,但是在C#中,静态成员仅可以通过类来调用。其实我们通常声明的时候,都在使用了C#中默认的关键字Auto,只不过没有显式写出而已,当类定义了一个非静态的数据时,这个类型的每一个对象都保存着一份私有副本。Auto是由程序自 动控制变量的生存周期,通常指的就是变量在进入其作用域(一般是由大括号控制)的时候被分配,离开其作用域的时候被释放;而static是变量在程序初始化时被分配,直到程序退出前才被释放;也就是说static是按照程序的生命周期来分配释放变量的,而不是变量自己的生命周期。如果是下面的代码:
class MyClass { int num1=0; static int num2=0; public void SomeMethod() { num1++; num2++; Console.WriteLine("num1为{0},num2为{1}",num1,num2); } } |
class Program { static void Main(string[] args) { MyClass m1 = new MyClass ();m1. SomeMethod (); MyClass m2 = new MyClass ();m2. SomeMethod (); MyClass m3 = new MyClass ();m3. SomeMethod (); Console.ReadLine(); } } |
1.6.1
结果如下:
num1为1,num2为1 num1为1,num2为2 num1为1,num2为3 |
程序在每次创建对象并调用这个方法时,num1都是新的,初始值都为0,因为它是在作用域开始时创建,结束时释放的。而num2就表现的十分镇静,每次累加都是在之前的基础之上累加,所以可以得出不管是否使用变量num2,它在程序初始化时已经分配了,或者是在第一次声明时就已经被分配了,所以无论怎么使用,指向的都是同一块内存空间的内容。
6.2 静态构造函数
前面提到过构造函数一般是用来做初始化的,但是假如我们在构造函数中给静态数据进行了初始化,那么虽然静态数据仅建立一次,但是在每次构造新对象时总会被还原成初始值。比如:
class MyClass { int num1 = 0; static int num2 ; public MyClass() {//实例构造函数 num2 = 0; } public void SomeMethod() { num1++; num2++; Console.WriteLine("num1为{0},num2为{1}", num1, num2); } } |
// Program类代码与1.6.1相同 |
1.6.2
结果如下:
num1为1,num2为1 num1为1,num2为1 num1为1,num2为1 |
如果想要通过其他方式(比如读取数据库或文件)将信息保存进静态数据中,以便之后使用,又仅想保证只在第一次创建对象时对其初始化的话,就必须考虑使用静态构造函数。于是将代码修改如下:
class MyClass { int num1 = 0; static int num2 ; static MyClass() {//静态构造函数 num2 = 0; } public void SomeMethod() { num1++; num2++; Console.WriteLine("num1为{0},num2为{1}", num1, num2); } } |
// Program类代码与1.6.1相同 |
1.6.3
结果如下:
num1为1,num2为1 num1为1,num2为2 num1为1,num2为3 |
这样就可以达到前面所说的目的。还有一些需要注意的:
静态构造函数
|
一个给定的类(或结构)只能定义一个静态构造函数 |
静态构造函数仅执行一次,与创建了多少个这种类型的对象无关 |
静态构造函数不带访问修饰符,也不能带任何参数 |
静态构造函数创建类实例时,或在调用者访问第一个静态成员之前,运行库会调用静态构造函数 |
静态构造函数在任何实例级别的构造函数之前运行 |
1.6.4
6.3 静态类
我们知道,在一个类中是可以出现静态成员和非静态成员的,而静态成员不允许通过类的实例来调用,这也许会让使用者有一些头疼,到底是应该如何调用呢?如果习惯了JAVA开发的程序员,会在实例化类后找不到所需的静态数据。于是在C# 2005后引入了静态类(static class)这个概念。被static修饰过的类只允许包含静态成员或常量数据,并且此类不允许使用NEW关键字来创建。
static class MyClass { const double PI = 3.14; static string name = "Mgod"; static MyClass() { }//静态构造函数,编译通过 private static void SomeMethod1() { }//通过 int num = 20;//报错,不能在静态类中声明实例成员 private void SomeMethod2() { }//报错,不能在静态类中拥有非静态成员 public MyClass(){}//报错,因为静态类不允许有实例构造函数 }
|
1.6.5
使用静态类更为简洁和安全,因为它限制了此类中必须拥有什么样类型的成员。更好理解。
(请看下回:你们先聊,我先走了! )
完稿日期:2009年1月16日 15点55分