Свойства (Руководство по программированию в C#)
Свойство — это член, предоставляющий гибкий механизм для чтения, записи или вычисления значения частного поля. Свойства можно использовать так, как если бы они являются открытыми элементами данных, но они являются специальными методами, называемыми методами доступа. Эта функция позволяет легко получать доступ к данным и по-прежнему способствует обеспечению безопасности и гибкости методов.
Общие сведения о свойствах
- Свойства позволяют классу предоставлять общий способ получения и задания значений, скрывая при этом код реализации или проверки.
- Метод доступа get используется для возврата значения свойства, а метод доступа set — для присвоения нового значения. В C# 9 и более поздних версий метод доступа к свойству init используется для назначения нового значения только при создании объекта. Эти методы доступа могут иметь различные уровни доступа. Дополнительные сведения см. в разделе Доступность методов доступа.
- Ключевое слово value используется для определения значения, присваиваемого методом доступа
set
илиinit
. - Свойства могут быть доступны для чтения и записи (они имеют оба метода доступа —
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#.