Статические члены и модификатор static

Последнее обновление: 27.12.2021

Кроме обычных полей, методов, свойств классы и структуры могут иметь статические поля, методы, свойства. Статические поля, методы, свойства относятся ко всему классу/всей структуре и для обращения к подобным членам необязательно создавать экземпляр класса / структуры.

Статические поля

Статические поля хранят состояние всего класса / структуры. Статическое поле определяется как и обычное, только перед типом поля указывается ключевое слово static. Например, рассмотрим класс Person, который представляет человека:

Person bob = new(68);
bob.СheckAge();     // Уже на пенсии

Person tom = new(37);
tom.СheckAge();     // Сколько лет осталось до пенсии: 28

// получение статического поля
Console.WriteLine(Person.retirementAge); // 65
// изменение статического поля
Person.retirementAge = 67;

class Person
{
    int age;
    public static int retirementAge = 65;
    public Person(int age)
    {
        this.age = age;
    }
    public void СheckAge()
    {
        if (age >= retirementAge)
			Console.WriteLine("Уже на пенсии");
        else
			Console.WriteLine($"Сколько лет осталось до пенсии: {retirementAge - age}");
    }
}

В данном случае класс Person имеет два поля: age (хранит возраст человека) и retirementAge (хранит пенсионный возраст). Однако поле retirementAge является статическим. Оно относится не к конкретному человеку, а ко всем людям. (В данном случае для упрощения пренебрежем тем фактом, что в зависимости от пола и профессии пенсионный возраст может отличаться.) Таким образом, поле retirementAge относится не к отдельную объекту и хранит значение НЕ отдельного объекта класса Person, а относится ко всему классу Person и хранит общее значение для всего класса.

Причем в самом классе мы можем использовать это поле как и любые другие. Так, в методе СheckAge(), который поверяет пенсионный статус человека, для проверки используем это поле:

if (age >= retirementAge)

Но если мы хотим обратиться к этому полю вне своего класса, то мы можем обращаться к этому полю по имени класса:

Console.WriteLine(Person.retirementAge);
Person.retirementAge = 67;

На уровне памяти для статических полей будет создаваться участок в памяти, который будет общим для всех объектов класса.

Статические методы класса в C#

При этом память для статических переменных выделяется даже в том случае, если не создано ни одного объекта этого класса.

Статические свойства

Подобным образом мы можем создавать и использовать статические свойства:

Person bob = new(68);
bob.СheckAge();

Console.WriteLine(Person.RetirementAge); // 65

class Person
{
    int age;
    static int retirementAge = 65;
    public static int RetirementAge
    {
        get { return retirementAge; }
        set { if (value > 1 && value < 100) retirementAge = value; }
    }
    public Person(int age)
    {
        this.age = age;
    }
    public void СheckAge()
    {
        if (age >= retirementAge)
            Console.WriteLine("Уже на пенсии");
        else
            Console.WriteLine($"Сколько лет осталось до пенсии: {retirementAge - age}") ;
    }
}

В данном случае доступ к статической переменной retirementAge опосредуется с помощью статического свойства RetirementAge.

Таким образом, переменные и свойства, которые хранят состояние, общее для всех объектов класса / структуры, следует определять как статические.

Нередко статические поля и свойства применяются для хранения счетчиков. Например, мы хотим иметь счетчик, который позволял бы узнать, сколько объектов Person создано:

var tom = new Person();
var bob = new Person();
var sam = new Person();
Console.WriteLine(Person.Counter);  // 3

class Person
{
    static int counter = 0;
    public static int Counter => counter;
    public Person()
    {
        counter++;
    }
}

В данном случае в классе Person счетчик хранится в приватной переменной counter, значение которой увеличивается на единицу при создании объекта в конструкторе. А с помощью статического свойства Counter, которое доступно только для чтения, мы можем получить значение счетчика.

Статические методы

Статические методы определяют общее для всех объектов поведение, которое не зависит от конкретного объекта. Для обращения к статическим методам также применяется имя класса / структуры:

Person bob = new(68);
Person.CheckRetirementStatus(bob);

class Person
{
    public int Age { get; set; }
    static int retirementAge = 65;
    public Person(int age) => Age = age;
    public static void CheckRetirementStatus(Person person)
    {
        if (person.Age >= retirementAge)
            Console.WriteLine("Уже на пенсии");
        else
            Console.WriteLine($"Сколько лет осталось до пенсии: {retirementAge - person.Age}") ;
    }
}

В данном случае в классе Person определен статический метод CheckRetirementStatus(), который в качестве параметра принимает объект Person и проверяет его пенсионный статус.

Следует учитывать, что статические методы могут обращаться только к статическим членам класса. Обращаться к нестатическим методам, полям, свойствам внутри статического метода мы не можем.

Статический конструктор

Кроме обычных конструкторов у класса также могут быть статические конструкторы. Статические конструкторы имеют следующие отличительные черты:

  • Статические конструкторы не должны иметь модификатор доступа и не принимают параметров

  • Как и в статических методах, в статических конструкторах нельзя использовать ключевое слово this для ссылки на текущий объект класса и можно обращаться только к статическим членам класса

  • Статические конструкторы нельзя вызвать в программе вручную. Они выполняются автоматически при самом первом создании объекта данного класса или при первом обращении к его статическим членам (если таковые имеются)

Статические конструкторы обычно используются для инициализации статических данных, либо же выполняют действия, которые требуется выполнить только один раз

Определим статический конструктор:

Console.WriteLine(Person.RetirementAge);

class Person
{
    static int retirementAge;
    public static int RetirementAge => retirementAge;
    static Person()
    {
        if (DateTime.Now.Year == 2022)
            retirementAge = 65;
        else
            retirementAge = 67;
    }
}

В данном случае с помощью встроенной структуры DateTime получаем текущий год. Для этого используется свойство DateTime.Now.Year. если он равен 2022, устанавливаем один пенсионный возраст. При другом значении текущего года устанавливается другое значение пенсионного возраста.

Статические классы

Статические классы объявляются с модификатором static и могут содержать только статические поля, свойства и методы. Например, определим класс, который выполняет ряд арифметических операций:

Console.WriteLine(Operations.Add(5, 4));         // 9
Console.WriteLine(Operations.Subtract(5, 4));    // 1
Console.WriteLine(Operations.Multiply(5, 4));    // 20

static class Operations
{
    public static int Add(int x, int y) => x + y;
    public static int Subtract(int x, int y) => x - y;
    public static int Multiply(int x, int y) => x * y;
}
Дополнительные материалы
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850