2.1 静态类成员和实例类成员
类成员分为成员变量和成员函数两种,有static修饰的类成员称为静态类成员,分为静态成员变量(类变量或类成员变量)和静态成员函数(类方法),没有static修饰的分别称为实例变量和实例方法。
类变量是被所有对象共享的,即所有对象的这个类变量是分配到同一个内存空间的,一个对象修改了这个类变量,那么其他对象的这个类变量的值也随之改变。
同样,类方法也是被所有对象共享的,所有对象的这个类方法被分配到的是同一个内存空间。
实例成员是对象所独有的,每个对象的实例成员分配到的内存空间不同。
类方法只能操作类变量,不能操作实例变量,实例方法可以操作任何类型的变量;类方法只能调用类中的其他类方法,实例方法可以调用类的任何方法。
2.2静态构造函数
使用静态成员变量时需要预先初始化,可以在定义时就提供一个初始值,但是若是要进行更复杂的初始化,或者在访问静态成员之前进行其他操作就要用到静态构造函数。
静态构造函数用于对静态成员进行初始化,静态构造函数用static修饰,不能有访问修饰符,也不能有任何参数,没有返回值且不能用void修饰。
静态构造函数不能手动调用,在如下情况系统会自动调用,且每个类只会调用一次:
1)创建包含静态构造函数的类实例时;
2)第一次访问包含静态构造函数的静态成员时。
静态构造函数只能初始化静态成员变量,不能初始化实例变量,且每个类只有一个静态构造函数
我们来做一个找错题,帮助我们一起来学习静态构造函数。
public class C { public static string BB; public static C() { BB = "CC"; } public static C(string mm) { BB = mm; } static C() { BB = "Right"; } public C() { BB = "Wrong"; } public C(string mm) { BB = mm; } }
VS编译提示的错误信息:
现在我们来做一个有意思的事情,验证静态构造函数的调用时机:
class Program { private static object lokk = new object(); static void Main(string[] args) { Console.WriteLine(B.strText); Console.WriteLine(A.strText); Console.ReadLine(); } } class A { public static string strText; public string Text; static A() { strText = "AAA"; } public A() { Text = "AAAAAAAAAA"; } } class B:A { static B() { strText = "BBB"; } public B() { Text = "BBBBBBBBBBBBBBB"; } }
输出结果均为:AAA
我们来分析一下出现这个情况的原因所在,当显示A.strText的时候,因为strText是静态变量,所以框架会调用A的静态构造函数,此时strText的值为AAA.正确
当显示B.strText的时候,因为B继承自A,所以会首先调用A的静态构造函数,但是因为静态构造函数只会调用一次,所以不会调用A的静态构造函数(因为显示A.strText已经调用过一次),但是又因为strText属于类A,而不是B,所以B得静态构造函数不会执行,故输出的均为AAA。
但是如果我们把输出更改一下,输出结果就大不一样了。
class Program { static void Main(string[] args) { B b = new B(); A a = new A(); Console.WriteLine(A.strText); Console.WriteLine(B.strText); Console.Read(); } } public class A { public static string strText; public string Text; static A() { strText = "AAA"; } public A() { Text = "AAAAAAAAAAAAAAAAAAAAAAAAAA"; } } public class B:A { static B() { strText = "BBB"; } public B() { Text = "BBBBBBBBBBBBBBBBB"; } }
请注意我在开始部分对类进行了实例化,那么此时的输出结果就是均为BBB。
为什么会有这样的情况出现呢,其实还是要从静态构造函数的调用时机入手。
首先我们实例化了B,此时会调用B的静态构造函数,但是因为strText是A的静态变量,所以首先会先调用A的静态构造函数将strText赋值为AAA,此时又会调用B的静态构造函数将strText赋值为BBB,所以此时strText的值应该为BBB,所以输出均为BBB。显示A.strText的时候不再调用A的静态构造函数。
参考https://www.cnblogs.com/jiagoushi/p/3775046.html
2.3静态类
只包含静态成员的类叫做静态类,静态类不包含实例构造函数,不能实例化,也不能继承,如Console类
static class A { public static string strText; static A() { strText = "AAA"; } }