静态成员变量从属于一个类而非某个具体的对象,它的值被该类的所有对象所共享.对于public的静态成员变量而言,它既可以由类名直接通过 “.” 操作符引用,也可以由对象名通过“.”操作符来引用,并且两者效果相同. 静态成员按照它们在类中声明的顺序进行初始化,并且此过程先于Main函数执行。
非静态成员变量则为独个对象所拥有,而不被各个对象所共享.因此不能用类名来直接引用.
例如: 在内存上的关系如下图所示(并不准确,仅用于理解) ,其中两个对象中的sMember均引用顶端的类的sMember,而nsMember则为各自所独有。
using System;
class MyClass
{
public int nsMember; //非静态成员变量
public static int sMember; //静态成员变量
public MyClass(int i, int j)
{ //成员的初始化
nsMember = i;
sMember = j;
}
}
class Test
{
static void Main()
{
MyClass mc1 = new MyClass(50, 100); //创建一个MyClass实例,并初始化.
Console.WriteLine(MyClass.sMember); //ok, sMember是MyClass类的静态成员,可以由类名直接引用. 此行输出100
Console.WriteLine(MyClass.nsMember);//出错!nsMember是非静态成员,不能由类名直接引用
Console.WriteLine(mc1.nsMember); //ok, mc是一个已成功创建的对象,它拥有自己的非静态成员nsMember
//此行输出50;
MyClass mc2 = new MyClass(10, 20); //创建一个新的实例,并初始化.
Console.WriteLine(MyClass.sMember); //ok,由于在mc2初始化时已更改sMember为20,而sMember为所有MyClass类对象所共享,
//故此行输出20.
Console.WriteLine(MyClass.nsMember);//同样出错!
Console.WriteLine(mc2.nsMember); //ok, 此行输出10;
Console.WriteLine(mc1.nsMember); //此行输出50,因为mc1和mc2的非静态成员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
关于静态构造函数
静态构造函数的执行发生在类的静态成员初始化之后和类的第一个实例创建之前.一个类只能定义一个静态构造函数,并且不能带有参数.
例如: 执行顺序如注释所标注.
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
静态构造函数不能被显式调用,且各个类中静态构造函数的调用顺序是不确定的.
例如: 有可能"Test2 Initialized"会在"Test1 Initialized"之前输出.
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 有可能"Test2 Initialized"会在"Test1 Initialized"之前输出.
非静态成员变量则为独个对象所拥有,而不被各个对象所共享.因此不能用类名来直接引用.
例如: 在内存上的关系如下图所示(并不准确,仅用于理解) ,其中两个对象中的sMember均引用顶端的类的sMember,而nsMember则为各自所独有。
using System;
class MyClass
{
public int nsMember; //非静态成员变量
public static int sMember; //静态成员变量
public MyClass(int i, int j)
{ //成员的初始化
nsMember = i;
sMember = j;
}
}
class Test
{
static void Main()
{
MyClass mc1 = new MyClass(50, 100); //创建一个MyClass实例,并初始化.
Console.WriteLine(MyClass.sMember); //ok, sMember是MyClass类的静态成员,可以由类名直接引用. 此行输出100
Console.WriteLine(MyClass.nsMember);//出错!nsMember是非静态成员,不能由类名直接引用
Console.WriteLine(mc1.nsMember); //ok, mc是一个已成功创建的对象,它拥有自己的非静态成员nsMember
//此行输出50;
MyClass mc2 = new MyClass(10, 20); //创建一个新的实例,并初始化.
Console.WriteLine(MyClass.sMember); //ok,由于在mc2初始化时已更改sMember为20,而sMember为所有MyClass类对象所共享,
//故此行输出20.
Console.WriteLine(MyClass.nsMember);//同样出错!
Console.WriteLine(mc2.nsMember); //ok, 此行输出10;
Console.WriteLine(mc1.nsMember); //此行输出50,因为mc1和mc2的非静态成员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
关于静态构造函数
静态构造函数的执行发生在类的静态成员初始化之后和类的第一个实例创建之前.一个类只能定义一个静态构造函数,并且不能带有参数.
例如: 执行顺序如注释所标注.
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
静态构造函数不能被显式调用,且各个类中静态构造函数的调用顺序是不确定的.
例如: 有可能"Test2 Initialized"会在"Test1 Initialized"之前输出.
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 有可能"Test2 Initialized"会在"Test1 Initialized"之前输出.