C# - 静态类, 静态方法, 静态构造器, 静态字段, Static Class, Methods, Constructors, Fields

在 C# 中,静态意味着无法实例化的东西。 您不能创建静态类的对象,也不能使用对象访问静态成员。

可以使用 static 修饰符关键字将 C# 类、变量、方法、属性、运算符、事件和构造函数定义为静态。

静态类 Static Class

在类名之前和访问修饰符之后应用静态修饰符,使类成为静态。 下面定义了一个带有静态字段和方法的静态类。

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"; // 把一个值赋给静态字段
    }
}

静态类规则

  • 静态类不能被实例化。
  • 静态类的所有成员都必须是静态的; 否则编译器会报错。
  • 静态类可以包含静态变量、静态方法、静态属性、静态运算符、静态事件和静态构造函数。
  • 静态类不能包含实例成员和构造函数。
  • 索引器和析构器不能是静态的
  • var 不能用于定义静态成员。 您必须在 static 关键字后显式指定成员类型。
  • 静态类是密封类,因此不能被继承。
  • 静态类不能从其他类继承。
  • 可以使用 ClassName.MemberName 访问静态类成员。
  • 静态类在您的程序所在的应用程序域的整个生命周期中都保留在内存中。

非静态类中的静态成员

普通类(非静态类)可以包含一个或多个静态方法、字段、属性、事件和其他非静态成员。

在一个非静态类中定义一些些静态成员定义比将整个类声明为静态更实用。

静态 字段 Static Fields

可以使用 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
    }
}

提示:在测试驱动开发当中。使用静态字段会让单元测试变成困难。

静态方法 Static Method

您可以在非静态类中定义一个或多个静态方法。 可以在不创建对象的情况下调用静态方法。 您不能使用非静态类的对象调用静态方法。

静态方法只能调用其他静态方法并访问静态成员。 您不能在静态方法中访问类的非静态成员。

    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 关键字定义静态方法。
  • 静态方法可以重载但不能被覆盖。
  • 静态方法可以包含局部静态变量。
  • 静态方法不能访问或调用非静态变量,除非它们作为参数传递。

静态构造函数 Static Constructors

非静态类可以包含无参数静态构造函数。 它可以使用 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被调用

静态构造函数规则

  • 静态构造函数是使用 static 关键字定义的,不使用访问修饰符 public、private 或 protected。
  • 一个非静态类可以包含一个无参数的静态构造函数。静态构造函数不能有参数 (因为现在也没有传参的机制)
  • 静态构造函数在生命周期中只会执行一次。 因此,如果一个类在多个地方被使用,您无法确定这个静态构造函数什么时候会被调用。
  • 静态构造函数只能访问静态成员。 它不能包含或访问实例成员。

静态成员存储在内存中称为高频堆(High-Frequency Heap)的特殊区域中。 非静态类的静态成员在类的所有实例之间共享。 因此,一个实例所做的更改将反映在所有其他实例中。

下一篇:C# 继承
最近更新的
...