C# 语言中,通过类名调用静态成员,通过指定的实例名调用实例成员。
1. static关键字
如果有些成员是所有对象共用的,此时可以将成员定义为静态的,当该类被装入内存时,系统会在内存中专门开辟一部分区域来保存这些静态成员。
static关键字表示类或成员加载到内存中只有一份,而不是有多个实例。当垃圾回收器检测到不再使用该静态成员后,会自动释放内存。
static 修饰符可用于类、字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类以外的类型。
static
静态字段常用的用法:
1. 记录已实例化对象的个数
2. 存储必须在所有实例之间共享的值
2. static 静态成员
static变量在对象被实例化时创建,通过对象进行访问一个类的所有实例的同一C#静态变量都是同一个值,同一个类的不同实例的同一非静态变量可以是不同的值。
static class CompanyEmployee
{
public static void DoSomething() { /*...*/ }
public static void DoSomethingElse() { /*...*/ }
public static cook;
}
- 非静态类可以包含静态的方法、字段、属性或事件;
- 无论对一个类创建多少个实例,它的静态成员都只有一个副本;
- 静态方法和属性不能访问其包含类型中的非静态字段和事件,并且不能访问任何对象的实例变量;
- 静态方法只能被重载,而不能被重写,因为静态方法不属于类的实例成员;
- 虽然字段不能声明为 static const,但 const 字段的行为在本质上是静态的。这样的字段属于类,不属于类的实例。因此,可以同对待静态字段一样使用 ClassName.MemberName 表示法来访问 const 字段;
- C# 不支持静态局部变量(在方法内部定义静态变量)。
- static 声明的静态成员在外部只能通过类名来引用,不能用实例名来引用
2. static 静态类
声明自定义类时如果加上static关键字,则该类就是静态类
一般将成员声明为静态,而不是将类声明为静态。如果将类声明为静态,则该类的所有成员都必须声明为静态的。
静态类可以用作只对输入参数进行操作并且不必获取或设置任何内部实例字段的方法集的方便容器。 例如,在 .NET Framework 类库中,静态 System.Math 类包含执行数学运算,而无需存储或检索对 Math 类特定实例唯一的数据的方法。 即,通过指定类名和方法名称来应用类的成员,如下面的示例所示。
double dub = -3.14;
Console.WriteLine(Math.Abs(dub));
Console.WriteLine(Math.Floor(dub));
Console.WriteLine(Math.Round(Math.Abs(dub)));
// Output:
// 3.14
// -4
// 3
加载引用静态类的程序时,CLR(公共语言运行库)可以保证在程序首次应用该类前自动加载该类,并初始化该类的字段以及调用静态其静态构造函数。静态类将一直保留在内存中,直至程序结束。
程序无法确切指定类加载的时间。 但是,可保证进行加载,以及在程序中首次引用类之前初始化其字段并调用其静态构造函数。 静态构造函数只调用一次,在程序所驻留的应用程序域的生存期内,静态类会保留在内存中。
静态类的主要功能:
1. 只包含静态成员。
2. 无法进行实例化。 (与私有构造函数机制类似)
3. 会进行密封seal,不能被继承,不能继承自任何类(除了 Object)。
4. 不能包含实例构造函数,但可包含静态构造函数。 如果在非静态类中包含需要进行重要的初始化的的静态成员,也需要声明为静态构造函数。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
StaticTest A, B;//定义类的变量
A = new StaticTest();//创建类的实例A
B = new StaticTest();//创建类的实例B
StaticTest.stal = StaticTest.stal + 10;//通过类名给静态变量赋值
A.a2 = A.a2 + 10;//给实例A的成员A2赋值
StaticTest.stal = StaticTest.stal + 10;//通过类名给静态变量赋值
B.a2 = B.a2 + 20;//给实例B的成员赋值
Console.WriteLine("StaticTest.stal+{0},A.a2={1}", StaticTest.stal, A.a2);//输出静态变量和实例A的成员a2的值
Console.WriteLine("StaticTest.stal+{0},B.a2={1}", StaticTest.stal, B.a2);//输出静态变量和实例B的成员a2的值
Console.ReadKey();
}
}
class StaticTest
{
public static int stal = 10;//定义静态变量
public int a2 = 10;//定义实例变量
}
}
3. static 静态构造函数
静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。 将在创建第一个实例或引用任何静态成员之前自动调用静态构造函数。
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline;
// Static constructor is called at most one time, before any
// instance constructor is invoked or member is accessed.
static SimpleClass()
{
baseline = DateTime.Now.Ticks;
}
}
静态构造函数具有以下属性:
- 静态构造函数不使用访问修饰符或不具有参数。
- 在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数以初始化类。
- 不能直接调用静态构造函数。
- 用户无法控制在程序中执行静态构造函数的时间。
- 静态构造函数只执行一次
- 静态构造函数的一种典型用法是在类使用日志文件且将构造函数用于将条目写入到此文件中时使用。
- 静态构造函数对于创建非托管代码的包装类也非常有用,这种情况下构造函数可调用 LoadLibrary 方法。
- 如果静态构造函数引发异常,运行时将不会再次调用该函数,并且类型在程序运行所在的应用程序域的生存期内将保持未初始化。
引用
http://www.cnblogs.com/linuxnotes/archive/2013/05/24/3096145.html
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members
http://blog.csdn.net/xifeijian/article/details/8708252
https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
C#程序设计及应用教程 v3 马骏