在 C# 中,静态意味着无法实例化的东西。 您不能创建静态类的对象,也不能使用对象访问静态成员。
可以使用 static 修饰符关键字将 C# 类、变量、方法、属性、运算符、事件和构造函数定义为静态。
在类名之前和访问修饰符之后应用静态修饰符,使类成为静态。 下面定义了一个带有静态字段和方法的静态类。
public static class Calculator
{
private static int _resultStorage = 0;
public static string Type = "Arithmetic";
public static int Sum(int num1, int num2)
{
return num1 + num2;
}
public static void Store(int result)
{
_resultStorage = result;
}
}
上面的 Calculator 类是静态的。 它的所有成员也是静态的。
您不能创建静态类的对象; 因此可以使用类名直接访问静态类的成员,如 ClassName.MemberName
,如下所示。
class Program
{
static void Main(string[] args)
{
var result = Calculator.Sum(10, 25); // 调用静态方法
Calculator.Store(result);
var calcType = Calculator.Type; // 访问静态变量
Calculator.Type = "Scientific"; // 把一个值赋给静态字段
}
}
ClassName.MemberName
访问静态类成员。普通类(非静态类)可以包含一个或多个静态方法、字段、属性、事件和其他非静态成员。
在一个非静态类中定义一些些静态成员定义比将整个类声明为静态更实用。
可以使用 static 关键字定义非静态类中的静态字段。
非静态类的静态字段在所有实例之间共享。 因此,一个实例所做的更改会反映在其他实例中。
class Program
{
public class StopWatch
{
public static int InstanceCounter = 0;
// instance constructor
public StopWatch()
{
InstanceCounter++;
}
public static int NoOfInstances
{
get { return InstanceCounter; }
}
}
static void Main(string[] args)
{
StopWatch sw1 = new StopWatch();
StopWatch sw2 = new StopWatch();
Console.WriteLine(StopWatch.NoOfInstances); //2
StopWatch sw3 = new StopWatch();
StopWatch sw4 = new StopWatch();
Console.WriteLine(StopWatch.NoOfInstances);//4
}
}
提示:在测试驱动开发当中。使用静态字段会让单元测试变成困难。
您可以在非静态类中定义一个或多个静态方法。 可以在不创建对象的情况下调用静态方法。 您不能使用非静态类的对象调用静态方法。
静态方法只能调用其他静态方法并访问静态成员。 您不能在静态方法中访问类的非静态成员。
class Program
{
static int counter = 0;
string name = "Demo Program";
static void Main(string[] args)
{
counter++; // 可以访问静态字段
Display("Hello World!"); // 可以访问静态方法
name = "New Demo Program"; //出错: 不能访问非静态成员 (需要实例化)
SetRootFolder("C:\\MyProgram"); //出错:不能访问非静态方法
}
static void Display(string text)
{
Console.WriteLine(text);
}
public void SetRootFolder(string path) { }
}
非静态类可以包含无参数静态构造函数。 它可以使用 static 关键字定义,而无需使用 public、private 和 protected 等访问修饰符。
下面的示例演示了静态构造函数和实例构造函数之间的区别。
public class StopWatch
{
// 静态构造函数
static StopWatch()
{
Console.WriteLine("静态构造函数被调用");
}
// 实例构造函数
public StopWatch()
{
Console.WriteLine("实例构造函数被调用");
}
// 静态方法
public static void DisplayInfo()
{
Console.WriteLine("DisplayInfo被调用");
}
// 实例方法
public void Start() { }
// 实例方法
public void Stop() { }
}
上面,非静态类 StopWatch 包含一个静态构造函数和一个非静态构造函数。 每当使用静态方法或第一次创建实例时,静态构造函数只会被调用一次。 下面的例子展示了静态构造函数在第一次调用静态方法时被调用。 第二次调用静态方法不会调用静态构造函数。
StopWatch.DisplayInfo(); // 静态构造函数会被调用一次
StopWatch.DisplayInfo(); // 静态构造函数不会再被调用
输出
静态构造函数被调用
DisplayInfo被调用
DisplayInfo被调用
以下示例显示在您第一次创建实例时调用静态构造函数。
StopWatch sw1 = new StopWatch(); // 先调用静态构造函数 然后调用实例构造函数
StopWatch sw2 = new StopWatch();// 只有实例构造函数被调用
StopWatch.DisplayInfo();
输出
静态构造函数被调用
实例构造函数被调用
实例构造函数被调用
DisplayInfo被调用
静态成员存储在内存中称为高频堆(High-Frequency Heap)的特殊区域中。 非静态类的静态成员在类的所有实例之间共享。 因此,一个实例所做的更改将反映在所有其他实例中。