static(C# 参考)

此页面介绍 static 修饰符关键字。 关键字 static 也是指令的 using static 一部分。

static使用修饰符声明属于类型本身而不是特定对象的静态成员。 static修饰符可用于声明static类。 在类、接口和结构中,可以将修饰符添加到 static 字段、方法、属性、运算符、事件和构造函数。 static修饰符不能与索引器或终结器一起使用。 有关详细信息,请参阅 静态类和静态类成员

可以将static修饰符添加到本地函数。 静态局部函数无法捕获局部变量或实例状态。

class Calc1
{
    public void CalculateSum()
    {
        int a = 3;
        int b = 7;

        // Static local function - cannot access 'a' or 'b' directly
        static int Add(int x, int y)
        {
            return x + y;
        }

        int result = Add(a, b); 
        Console.WriteLine($"Sum: {result}");
    }
}
  /*
 Output:
 Sum: 10
 */

可以将修饰符添加到 staticlambda 表达式匿名方法。 静态 lambda 或匿名方法无法捕获本地变量或实例状态。

class Calc2
{
    static void Main()
    {
        Func<int, int, int> add = static (a, b) => a + b;

        int result = add(5, 10);
        Console.WriteLine($"Sum: {result}");
    }
}
/*
Output:
Sum: 15
*/

示例 - 静态类

以下类声明为 static 仅包含 static 方法:

static class CompanyEmployee
{
    public static void DoSomething() { /*...*/ }
    public static void DoSomethingElse() { /*...*/  }
}

常量或类型声明是 static 隐式成员。 一个static成员不能通过实例引用。 然而,可以通过类型名称引用它。 例如,请考虑以下类:

public class MyBaseC
{
    public struct MyStruct
    {
        public static int x = 100;
    }
}

若要引用 static 成员 x,除非可从相同范围访问该成员,否则请使用完全限定的名称 MyBaseC.MyStruct.x

Console.WriteLine(MyBaseC.MyStruct.x);

虽然类的实例包含该类的所有实例字段的单独副本,但每个 static 字段只有一个副本。 对于泛型类型,每个关闭的泛型类型都有自己的静态字段副本。 标记为 ThreadStaticAttribute 的静态字段在每个线程中都有一个副本。

不能使用 this 引用 static 的方法或属性访问器。

如果关键字 static 应用于类,则类的所有成员都必须是 static

类、接口和 static 类可能具有 static 构造函数。 static在程序启动时和类实例化之间的某个时间点调用构造函数。

注释

与C++相比,关键字 static 的使用有限。 若要与 C++ 关键字进行比较,请参阅存储类(C++)。

若要演示 static 成员,可以考虑一个用于表示公司员工的类。 假设该类包含用于计算员工数的方法,以及用于存储员工数的字段。 方法和字段均不属于任何一个员工实例。 相反,他们属于整个员工类。 它们应该被声明为类 static 的成员。

示例 - 静态字段和方法

此示例读取新员工的姓名和 ID,员工计数器按 1 递增,并显示新员工信息和新员工人数。 此程序从键盘输入当前员工数。

public class Employee4
{
    public string id;
    public string name;

    public Employee4()
    {
    }

    public Employee4(string name, string id)
    {
        this.name = name;
        this.id = id;
    }

    public static int employeeCounter;

    public static int AddEmployee()
    {
        return ++employeeCounter;
    }
}

class MainClass : Employee4
{
    static void Main()
    {
        Console.Write("Enter the employee's name: ");
        string name = Console.ReadLine();
        Console.Write("Enter the employee's ID: ");
        string id = Console.ReadLine();

        // Create and configure the employee object.
        Employee4 e = new Employee4(name, id);
        Console.Write("Enter the current number of employees: ");
        string n = Console.ReadLine();
        Employee4.employeeCounter = Int32.Parse(n);
        Employee4.AddEmployee();

        // Display the new information.
        Console.WriteLine($"Name: {e.name}");
        Console.WriteLine($"ID:   {e.id}");
        Console.WriteLine($"New Number of Employees: {Employee4.employeeCounter}");
    }
}
/*
Input:
Matthias Berndt
AF643G
15
 *
Sample Output:
Enter the employee's name: Matthias Berndt
Enter the employee's ID: AF643G
Enter the current number of employees: 15
Name: Matthias Berndt
ID:   AF643G
New Number of Employees: 16
*/

示例 - 静态初始化

此示例演示如何使用尚未声明的另一个staticstatic字段来初始化字段。 在向字段显式分配值 static 之前,结果将未定义。

class Test
{
    static int x = y;
    static int y = 5;

    static void Main()
    {
        Console.WriteLine(Test.x);
        Console.WriteLine(Test.y);

        Test.x = 99;
        Console.WriteLine(Test.x);
    }
}
/*
Output:
    0
    5
    99
*/

C# 语言规范

有关详细信息,请参阅 C# 语言规范。 语言规范是 C# 语法和用法的明确来源。

另请参阅