Свойства (Руководство по программированию в C#)

Свойство — это член, предоставляющий гибкий механизм для чтения, записи или вычисления значения частного поля. Свойства можно использовать, как если бы они являются общедоступными элементами данных, но они являются специальными методами, называемыми методами доступа. Эта функция позволяет легко получать доступ к данным и по-прежнему способствовать обеспечению безопасности и гибкости методов.

Общие сведения о свойствах

  • Свойства позволяют классу предоставлять общий способ получения и задания значений, скрывая при этом код реализации или проверки.
  • Метод доступа get используется для возврата значения свойства, а метод доступа set — для присвоения нового значения. Метод доступа к свойству init используется для назначения нового значения только во время построения объекта. Эти методы доступа могут иметь различные уровни доступа. Дополнительные сведения см. в разделе Доступность методов доступа.
  • Значение ключевое слово используется для определения значенияsetinit, которое назначает или метод доступа.
  • Свойства могут быть доступны для чтения и записи (они имеют оба метода доступа — get и set), только для чтения (они имеют метод доступа get, но не имеют метода доступа set) или только для записи (они имеют метод доступа set, но не имеют метода доступа get). Свойства только для записи встречаются редко и чаще всего используются для ограничения доступа к конфиденциальным данным.
  • Простые свойства, не требующие пользовательского кода метода доступа, можно реализовать как определения текста выражений или как автоматически реализуемые свойства.

Свойства с резервными полями

Одной из базовых схем реализации свойств является использование закрытого резервного поля для установки и извлечения значения свойства. Метод доступа get возвращает значение закрытого поля, а метод доступа set может выполнять определенные проверки данных до присвоения значению закрытого поля. Оба метода доступа также могут выполнять некоторые преобразования или вычисления данных перед его сохранением или возвратом.

Это показано в следующем примере. В этом примере класс TimePeriod представляет интервал времени. На внутреннем уровне класс сохраняет интервал времени в секундах в закрытом поле с именем _seconds. Свойство чтения и записи с именем Hours позволяет клиенту указывать временной интервал в часах. Методы доступа get и set выполняют необходимое преобразование между часами и секундами. Кроме того, метод доступа set проверяет данные и создает ArgumentOutOfRangeException, если указано недопустимое количество часов.

public class TimePeriod
{
    private double _seconds;

    public double Hours
    {
        get { return _seconds / 3600; }
        set
        {
            if (value < 0 || value > 24)
                throw new ArgumentOutOfRangeException(nameof(value),
                      "The valid range is between 0 and 24.");

            _seconds = value * 3600;
        }
    }
}

Чтобы получить и задать значение, можно получить и задать свойства, как показано в следующем примере:

TimePeriod t = new TimePeriod();
// The property assignment causes the 'set' accessor to be called.
t.Hours = 24;

// Retrieving the property causes the 'get' accessor to be called.
Console.WriteLine($"Time in hours: {t.Hours}");
// The example displays the following output:
//    Time in hours: 24

Определения текста выражений

Как правило, методы доступа к свойствам состоят из однострочных операторов, которые просто назначают или возвращают результат выражения. Эти свойства можно реализовать как члены, воплощающие выражение. Определения текста выражений состоят из символа =>, за которым идет выражение, назначаемое свойству или извлекаемое из него.

Свойства, доступные только для чтения, могут реализовать get метод доступа в качестве элемента, на основе выражения. В этом случае не используется ни ключевое слово метода доступа get, ни ключевое слово return. В следующем примере показана реализация свойства только для чтения Name в виде члена, воплощающего выражение.

public class Person
{
    private string _firstName;
    private string _lastName;

    public Person(string first, string last)
    {
        _firstName = first;
        _lastName = last;
    }

    public string Name => $"{_firstName} {_lastName}";
}

И get метод set доступа могут быть реализованы как члены с выражением. В этом случае необходимо указывать ключевые слова get и set. В следующем примере показано использование определений текста выражений для обоих методов доступа. Ключевое слово return не используется с методом get доступа.

public class SaleItem
{
    string _name;
    decimal _cost;

    public SaleItem(string name, decimal cost)
    {
        _name = name;
        _cost = cost;
    }

    public string Name
    {
        get => _name;
        set => _name = value;
    }

    public decimal Price
    {
        get => _cost;
        set => _cost = value;
    }
}

Автоматически реализуемые свойства

В некоторых случаях свойства get и set методы доступа просто назначают значение или извлекают значение из резервного поля, не включая дополнительную логику. С помощью автоматически реализуемых свойств можно упростить код, в то время как компилятор C# будет прозрачно предоставлять вам резервное поле.

Если у свойства есть методы доступа get и set (или get и init), они оба должны быть автоматически реализованы. Автоматически реализуемое свойство определяется с помощью ключевых слов get и set без указания какой-либо реализации. Следующий пример аналогичен предыдущему, за исключением того, что Name и Price являются автоматически реализуемыми свойствами. В этом примере также удаляется параметризованный конструктор, что позволяет инициализировать объекты SaleItem, вызывая конструктор без параметров и инициализатор объекта.

public class SaleItem
{
    public string Name
    { get; set; }

    public decimal Price
    { get; set; }
}

Автоматически реализованные свойства могут объявлять различные специальные возможности для get методов доступа и set доступа. Обычно вы объявляете общедоступный get метод доступа и частный set метод доступа. Дополнительные сведения см. в статье об ограничении специальных возможностей доступа.

Обязательные свойства

Начиная с C# 11, можно добавить required член, чтобы принудительно инициализировать любое свойство или поле клиентского кода:

public class SaleItem
{
    public required string Name
    { get; set; }

    public required decimal Price
    { get; set; }
}

Чтобы создать SaleItemобъект, необходимо задать как свойства, так Name и Price свойства с помощью инициализаторов объектов, как показано в следующем коде:

var item = new SaleItem { Name = "Shoes", Price = 19.95m };
Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");

Спецификация языка C#

Дополнительные сведения см. в разделе Свойства в Спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также