Menu
Coddy logo textTech

Экземплярные и статические данные

Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy — урок 15 из 70.

Теперь, когда вы понимаете статические члены, давайте проясним, когда использовать данные экземпляра, а когда статические данные. Это решение определяет то, как ваш класс хранит и передает информацию.

Данные экземпляра принадлежат каждому объекту индивидуально. Каждый объект получает свою собственную копию, и изменения в одном объекте не влияют на другие:

public class BankAccount
{
    public string Owner { get; set; }      // Экземпляр — уникально для каждого счета
    public decimal Balance { get; set; }   // Экземпляр — уникально для каждого счета
}

У каждого BankAccount есть свой владелец и баланс. Это логично, так как разные счета содержат разные суммы для разных людей.

Статические данные принадлежат самому классу и являются общими для всех экземпляров:

public class BankAccount
{
    public static decimal InterestRate = 0.05m;  // Статическое — одинаково для всех
    public static int TotalAccounts = 0;         // Статическое — отслеживает все счета
    
    public string Owner { get; set; }
    public decimal Balance { get; set; }
}

Процентная ставка применяется одинаково к каждому счету, поэтому логично сделать её статической (static). Общий счетчик аккаунтов отслеживает информацию на уровне всего класса, а не данные конкретного счета.

Простое правило: если данные описывают конкретный объект, сделайте их полями экземпляра (instance). Если они описывают класс в целом или должны быть общими, сделайте их статическими (static). Неправильное их смешивание приводит к ошибкам, при которых данные неожиданно меняются во всех объектах или становятся недоступны в нужный момент.

challenge icon

Задание

Легко

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

Вы создадите два файла для организации вашего кода:

  • Player.cs: Определите класс Player в пространстве имен GameSession. У каждого игрока есть свои собственные Username (string) и Score (int) — они уникальны для каждого игрока. Класс также должен отслеживать информацию, которая относится ко всем игрокам: статическое поле GameName (string), в котором хранится название игры, в которую все играют, и статическое поле TotalPlayers (int), которое подсчитывает, сколько игроков присоединилось. Включите конструктор, который принимает имя пользователя и начальный счет и автоматически увеличивает общее количество игроков. Добавьте статический метод SetGameName(string name) для настройки названия игры.
  • Program.cs: В основном файле настройте игру и создайте игроков на основе входных данных. Сначала установите название игры, затем создайте двух игроков и выведите их индивидуальную информацию вместе с общими данными игры.

Вы получите пять входных данных:

  • Название игры
  • Имя пользователя первого игрока
  • Начальный счет первого игрока
  • Имя пользователя второго игрока
  • Начальный счет второго игрока

Выведите результат в следующем формате:

Game: {GameName}
Player: {Username}, Score: {Score}
Player: {Username}, Score: {Score}
Total Players: {TotalPlayers}

Например, если входные данные — BattleArena, DragonSlayer, 1500, ShadowNinja и 2200, вывод должен быть следующим:

Game: BattleArena
Player: DragonSlayer, Score: 1500
Player: ShadowNinja, Score: 2200
Total Players: 2

Подумайте внимательно о том, какие данные должны быть привязаны к экземпляру (разные для каждого игрока), а какие должны быть статическими (общими для всех игроков). Название игры и общее количество игроков описывают сессию в целом, в то время как имя пользователя и счет уникальны для каждого отдельного человека.

Шпаргалка

Используйте данные экземпляра для свойств, которые уникальны для каждого объекта:

public class BankAccount
{
    public string Owner { get; set; }      // У каждого счета свой владелец
    public decimal Balance { get; set; }   // У каждого счета свой баланс
}

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

public class BankAccount
{
    public static decimal InterestRate = 0.05m;  // Одинаково для всех счетов
    public static int TotalAccounts = 0;         // Отслеживает все счета
    
    public string Owner { get; set; }
    public decimal Balance { get; set; }
}

Правило принятия решения: Если данные описывают конкретный объект, используйте данные экземпляра. Если они описывают класс в целом или должны быть общими, используйте статические данные.

Попробуйте сами

using System;

namespace GameSession
{
    class Program
    {
        public static void Main(string[] args)
        {
            // Чтение входных данных
            string gameName = Console.ReadLine();
            string username1 = Console.ReadLine();
            int score1 = Convert.ToInt32(Console.ReadLine());
            string username2 = Console.ReadLine();
            int score2 = Convert.ToInt32(Console.ReadLine());

            // TODO: Установите название игры, используя статический метод

            // TODO: Создайте два объекта Player с входными данными

            // TODO: Выведите результат в требуемом формате
            // Game: {GameName}
            // Player: {Username}, Score: {Score}
            // Player: {Username}, Score: {Score}
            // Total Players: {TotalPlayers}
        }
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование