C# Static关键字

it2023-08-29  68

C# Static关键字

静态类

1.只能包含静态成员(静态方法或静态变量),非静态成员是不能使用的,而非静态类可以包含静态的方法、字段、属性或事件,且无论对这个非静态类创建多少个实例,它的静态成员都只有一个。

2.不能对其实例化。

3.不能被继承,因为静态类本质是一个抽象的密封类。

4.不能包含实例构造函数

实例构造函数

1、构造函数的名字与类名相同。

2、使用 new 表达式创建类的对象或者结构(例如int)时,会调用其构造函数。并且通常初始化新对象的数据成员。

3、除非类是静态的,否则会为没有构造函数的类,自动生成一个默认构造函数,并使用默认值来初始化对象字段。

4、构造函数可以有参数,可以以多态的形式存在多个构造函数。

静态构造函数

1.静态构造函数不使用访问修饰符或不具有参数。(不加访问修饰符默认为private)

2.在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数以初始化类。

3.不能直接调用静态构造函数。

4.执行顺序:静态变量 > 静态构造函数 > 静态函数

5.执行顺序:静态变量 > 静态构造函数 > 构造函数

class Program { public static int x = 0;//静态变量 //静态构造函数 static Program() { x = 1; } //构造函数 Program() { x = 2; } private static void Main(string[] args)//程序入口,当执行到 Main时,执行public static int x = 0;接着执行静态构造函数(即上面的第二点) { System.Console.WriteLine("x={0}", x); Program p = new Program();//执行构造函数 System.Console.WriteLine("x={0}", x); System.Console.Read(); } } //执行结果:x=1,x=2

创建某个类型的第一个实例时,所进行的操作顺序为: 1.静态变量设置为0 2.执行静态变量初始化器 3.执行基类的静态构造函数 4.执行静态构造函数 5.实例变量设置为0 6.执行实例变量初始化器 7.执行基类中合适的实例构造函数 8.执行实例构造函数 即:子类静态变量初始化>子类静态构造函数>父类静态变量初始化 > 父类静态构造函数 > 父类实例变量初始化>父类实例构造函数 > 子类实例变量初始化>本身实例构造函数。

public class A { public static readonly int x; static A() { x = B.y + 1; } } public class B { public static int y = A.x + 1; public static void Main(string[] args) { Console.WriteLine("x:{0},y:{1}。", A.x, y); Console.ReadLine(); } } 1、首先,每一个项目有且只能有一个静态类的Main函数作为入口函数。而入口函数是最先执行的。 2、由于Main函数在B类里面,首先会初始化B类。而类的初始化顺序是:类里的静态变量,然后执行静态构造函数。 3、运行起先执行 public static int y = A.x + 1 这个,执行的时候,会先把 y 初始化为0,然后计算 y 的值。 4、计算 y 的值的时候,调用了 A 的静态变量 x 。所以会先初始化A。 5、初始化A时首先去执行 public static readonly int x ,先把 x 初始化为0。 6、然后执行A的静态构造函数 x = B.y + 1 此时 y 已经初始化为0了。 7、计算得到 x = 1。然后回到 public static int y = A.x + 1 得到 y = 2。 8、然后再执行Main函数的内容。得出结果x=1,y=2 //父类 class animal { public static int leg; public int head; static animal() { System.Console.WriteLine("animal的静态构造函数,leg={0}", leg); } public animal() { System.Console.WriteLine("animal的实例构造函数,head={0}", head); } } //子类 class dog:animal { public static int leg; public int head; public dog() { head = 1; System.Console.WriteLine("dog的实例构造方法,head={0}", head); } static dog() { leg = 1; System.Console.WriteLine("dog的静态构造方法,leg={0}", leg); } } //主函数 private static void Main(string[] args) { dog d = new dog(); } 运行结果: dog的静态构造方法,leg=1 animal的静态构造函数,leg=0 animal的实例构造函数,head=0 dog的实例构造方法,head=1 //子类静态变量初始化>子类静态构造函数>父类静态变量初始化 > 父类静态构造函数 > 父类实例变量初始化>父类实例构造函数 > 子类实例变量初始化>本身实例构造函数。

静态变量

1.static只能修饰成员变量,不能修饰局部变量。(在类中定义的变量称为成员变量,在整个类中都有效;在方法中定义的变量称为局部变量,当前定义的方法内有效,方法调用被销毁,不能在其他类中进行调用) 2.表示每次重新使用该变量所在方法、类或自定义类时,变量的值为程序这次运行最后一次为变量赋值时的值。 3.静态变量一直记录变量的值,一直到下次赋值时。 4.不同线程下访问的静态属性总是同一属性,如果某一线程更改了属性值,将造成其他线程访问属性值的错误。因此方法中访问同一静态属性就需要使用lock关键字,或创建互斥对象来保持静态属性在同一时间只能被某一对象的属性或方法访问。 5.静态成员只被创建一次,所以静态成员只有一份,而实例成员有多少个对象,就有多少个成员。

class program2 { public static int x; public static void func() { x += 1; } } private static void Main(string[] args) { program2.func(); System.Console.WriteLine("x={0}", program2.x); program2.func(); System.Console.WriteLine("x={0}", program2.x); System.Console.Read(); } 结果:x=1,x=2

静态方法

1.在方法(函数)前用static修饰,表示此方法为所在类或所在自定义类所有,而不是这个类的实例所有。

2.在静态方法中只能直接调用同类中其他的静态成员(包括变量和方法), 而不能直接访问类中的非静态成员。

3.每一个线程在同一时间访问的静态方法都是不同的,因此静态方法在多线程调用中不会产生冲突。

4.在静态方法中不能直接调用实例成员,因为静态方法被调用时,对象还有可能不存在。

5.this/base关键字在静态方法不能使用,因为有可能对象还不存在。

6.静态方法只能被重载,不能被重写,因为静态方法不属于类的实例成员。

class program2 { public static int x; public static void func() { x += 1; } } private static void Main(string[] args) { program2 p = new program2(); p.func();//报错,无法使用实例引用访问func(),因为此方法为所在类或所在自定义类所有,而不是这个类的实例所有。 }

应用场景

1.当变量需要被共享时可以将变量定义为静态变量。

2.当方法需要被反复调用时可以将方法定义为静态方法。

3.当一个类中包含的成员都是静态时可以将类定义为静态类。

最新回复(0)