C#中的静态与非静态成员入门
静态和非静态成员虽然是非常基本的知识,但对于编程入门者而言确又不易理解。虽然我也是新手,但也希望写下一点咚咚给新新手门参考. 下面对C#中的静态和非静态成员的用法做了一点简单介绍,为了便于理解,没有提到底层编译的运作过程,只对其用法做一些介绍。
关于静态成员变量和非静态成员变量
静态成员变量从属于一个类而非某个具体的对象,它的值被该类的所有对象所共享.对于public的静态成员变量而言,它既可以由类名直接通过 “.” 操作符引用,也可以由对象名通过“.”操作符来引用,并且两者效果相同. 静态成员按照它们在类中声明的顺序进行初始化,并且此过程先于Main函数执行。
非静态成员变量则为独个对象所拥有,而不被各个对象所共享.因此不能用类名来直接引用.
例如:
1 using System;
2
3 class MyClass
4 {
5 public int nsMember; //非静态成员变量
6 public static int sMember; //静态成员变量
7
8 public MyClass(int i, int j)
9 { //成员的初始化
10 nsMember = i;
11 sMember = j;
12 }
13 }
14
15 class Test
16 {
17 static void Main()
18 {
19 MyClass mc1 = new MyClass(50, 100); //创建一个MyClass实例,并初始化.
20
21 Console.WriteLine(MyClass.sMember); //ok, sMember是MyClass类的静态成员,可以由类名直接引用. 此行输出100
22 Console.WriteLine(MyClass.nsMember);//出错!nsMember是非静态成员,不能由类名直接引用
23 Console.WriteLine(mc1.nsMember); //ok, mc是一个已成功创建的对象,它拥有自己的非静态成员nsMember
24 //此行输出50;
25 MyClass mc2 = new MyClass(10, 20); //创建一个新的实例,并初始化.
26
27 Console.WriteLine(MyClass.sMember); //ok,由于在mc2初始化时已更改sMember为20,而sMember为所有MyClass类对象所共享,
28 //故此行输出20.
29 Console.WriteLine(MyClass.nsMember);//同样出错!
30
31 Console.WriteLine(mc2.nsMember); //ok, 此行输出10;
32
33 Console.WriteLine(mc1.nsMember); //此行输出50,因为mc1和mc2的非静态成员nsMember是互相独立的
34
35 }
36 }
37
2
3 class MyClass
4 {
5 public int nsMember; //非静态成员变量
6 public static int sMember; //静态成员变量
7
8 public MyClass(int i, int j)
9 { //成员的初始化
10 nsMember = i;
11 sMember = j;
12 }
13 }
14
15 class Test
16 {
17 static void Main()
18 {
19 MyClass mc1 = new MyClass(50, 100); //创建一个MyClass实例,并初始化.
20
21 Console.WriteLine(MyClass.sMember); //ok, sMember是MyClass类的静态成员,可以由类名直接引用. 此行输出100
22 Console.WriteLine(MyClass.nsMember);//出错!nsMember是非静态成员,不能由类名直接引用
23 Console.WriteLine(mc1.nsMember); //ok, mc是一个已成功创建的对象,它拥有自己的非静态成员nsMember
24 //此行输出50;
25 MyClass mc2 = new MyClass(10, 20); //创建一个新的实例,并初始化.
26
27 Console.WriteLine(MyClass.sMember); //ok,由于在mc2初始化时已更改sMember为20,而sMember为所有MyClass类对象所共享,
28 //故此行输出20.
29 Console.WriteLine(MyClass.nsMember);//同样出错!
30
31 Console.WriteLine(mc2.nsMember); //ok, 此行输出10;
32
33 Console.WriteLine(mc1.nsMember); //此行输出50,因为mc1和mc2的非静态成员nsMember是互相独立的
34
35 }
36 }
37
在内存上的关系如下图所示(并不准确,仅用于理解) ,其中两个对象中的sMember均引用顶端的类的sMember,而nsMember则为各自所独有。
。。。 。。。 |
sMember |
。。。 。。。 |
mc1 |
nsMember(50) |
sMember |
mc2 |
nsMember(10) |
sMember |
关于静态方法和非静态方法
类似静态成员变量,静态方法为一个类所拥有.但静态方法中只能使用静态成员,而不能使用非静态成员.
非静态方法中既能使用静态成员,也能使用非静态成员.
例如,为上面的MyClass类添加一个静态方法StaticFun()和一个非静态方法UStaticFun()
1 class MyClass
2 {
3
4 static void StaticFun()
5 {
6 nsMember += nsMember; //出错!因为nsMember是非静态成员
7 sMember += sMember; //ok,因为sMember是静态成员
8 }
9
10 void UStaticFun()
11 {
12 nsMember += nsMember; //ok
13 sMember += sMember; //ok
14 }
15 }
16
2 {
3
4 static void StaticFun()
5 {
6 nsMember += nsMember; //出错!因为nsMember是非静态成员
7 sMember += sMember; //ok,因为sMember是静态成员
8 }
9
10 void UStaticFun()
11 {
12 nsMember += nsMember; //ok
13 sMember += sMember; //ok
14 }
15 }
16
关于静态构造函数
静态构造函数的执行发生在类的静态成员初始化之后和类的第一个实例创建之前.一个类只能定义一个静态构造函数,并且不能带有参数.
例如:
1 class InitOrder
2 {
3 static int sMember1 = 1; // 1
4 static int sMember2 = 2; // 2
5
6 InitOrder()
7 {
8 Console.WriteLine("unstatic ctor initialized"); // 4
9 }
10
11 static InitOrder()
12 {
13 Console.WriteLine("static ctor initialized"); // 3
14 }
15 }
16
17 class Test
18 {
19 static void Main()
20 {
21 InitOrder io = new InitOrder();
22 }
23 }
24
2 {
3 static int sMember1 = 1; // 1
4 static int sMember2 = 2; // 2
5
6 InitOrder()
7 {
8 Console.WriteLine("unstatic ctor initialized"); // 4
9 }
10
11 static InitOrder()
12 {
13 Console.WriteLine("static ctor initialized"); // 3
14 }
15 }
16
17 class Test
18 {
19 static void Main()
20 {
21 InitOrder io = new InitOrder();
22 }
23 }
24
静态构造函数不能被显式调用,且各个类中静态构造函数的调用顺序是不确定的.
例如:
1 class Test1
2 {
3 public static void Print()
4 {
5 Console.WriteLine("Print1 is called");
6 }
7 static Test1()
8 {
9 Console.WriteLine("Test1 Initialized");
10 }
11 }
12
13 class Test2
14 {
15 public static void Print()
16 {
17 Console.WriteLine("Print2 is called");
18 }
19 static Test2()
20 {
21 Console.WriteLine("Test2 Initialized");
22 }
23 }
24
25 class Test
26 {
27 static void Main()
28 {
29 Test1.Print();
30 Test2.Print();
31 }
32 }
33
2 {
3 public static void Print()
4 {
5 Console.WriteLine("Print1 is called");
6 }
7 static Test1()
8 {
9 Console.WriteLine("Test1 Initialized");
10 }
11 }
12
13 class Test2
14 {
15 public static void Print()
16 {
17 Console.WriteLine("Print2 is called");
18 }
19 static Test2()
20 {
21 Console.WriteLine("Test2 Initialized");
22 }
23 }
24
25 class Test
26 {
27 static void Main()
28 {
29 Test1.Print();
30 Test2.Print();
31 }
32 }
33