Перейти к содержимому

Get set c что это

  • автор:

Что такое Аксессоры «get» и «set» в C#?

Благодаря аксессорам мы можем выполнять дополнительный код при установке или же при взятии значения у какой-либо переменной. Обычно программисты называют аксессоры точно также как и переменную, с которой идет работа, но первый символ указывается в верхнем регистре. Пример использования аксессоров привиден ниже:

using System; namespace ProjectOne < class Book < private string name; public string Name < get < Console.Write("Take your name, " + this.name); return name; >set < this.name = value; Console.Write("Hello, " + this.name); >> > class MainClass < public static void Main (string[] args) < Book sherlock = new Book(); sherlock.Name = "Sherlock Holms"; >> >

Такая программа выведет на экран «Hello, Sherlock Holms». Аксессоры очень удобны, они как небольшие функции, служащие для работы лишь с одной переменной.

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

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

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

  • Свойства позволяют классу предоставлять общий способ получения и задания значений, скрывая при этом код реализации или проверки.
  • Метод доступа get используется для возврата значения свойства, а метод доступа set — для присвоения нового значения. Метод доступа к свойству 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: "); // 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 => $" "; > 

И 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($": sells for "); 

См. также

  • Использование свойств
  • Свойства интерфейса
  • Сравнение свойств и индексаторов
  • Ограничение доступности методов доступа
  • Автоматически реализуемые свойства

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

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

См. также

  • Индексаторы
  • Ключевое слово get
  • Ключевое слово set

Совместная работа с нами на GitHub

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

Get set c что это

Кроме обычных методов в языке C# предусмотрены специальные методы доступа, которые называют свойства . Они обеспечивают простой доступ к полям классов и структур, узнать их значение или выполнить их установку.

Определение свойств

Стандартное описание свойства имеет следующий синтаксис:

[модификаторы] тип_свойства название_свойства < get < действия, выполняемые при получении значения свойства>set < действия, выполняемые при установке значения свойства>>

Вначале определения свойства могут идти различные модификаторы, в частности, модификаторы доступа. Затем указывается тип свойства, после которого идет название свойства. Полное определение свойства содержит два блока: get и set .

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

В блоке set устанавливается значение свойства. В этом блоке с помощью параметра value мы можем получить значение, которое передано свойству.

Блоки get и set еще называются акссесорами или методами доступа (к значению свойства), а также геттером и сеттером.

Person person = new Person(); // Устанавливаем свойство - срабатывает блок Set // значение "Tom" и есть передаваемое в свойство value person.Name = "Tom"; // Получаем значение свойства и присваиваем его переменной - срабатывает блок Get string personName = person.Name; Console.WriteLine(personName); // Tom class Person < private string name = "Undefined"; public string Name < get < return name; // возвращаем значение свойства >set < name = value; // устанавливаем новое значение свойства >> >

Здесь в классе Person определено приватное поле name , которая хранит имя пользователя, и есть общедоступное свойство Name . Хотя они имеют практически одинаковое название за исключением регистра, но это не более чем стиль, названия у них могут быть произвольные и не обязательно должны совпадать.

Через это свойство мы можем управлять доступом к переменной name . В свойстве в блоке get возвращаем значение поля:

А в блоке set устанавливаем значение переменной name. Параметр value представляет передаваемое значение, которое передается переменной name.

В программе мы можем обращаться к этому свойству, как к обычному полю. Если мы ему присваиваем какое-нибудь значение, то срабатывает блок set , а передаваемое значение передается в параметр value :

person.Name = "Tom";

Если мы получаем значение свойства, то срабатывает блок get , который по сути возвращает значение переменной name:

string personName = person.Name;

То есть по сути свойство Name ничего не хранит, оно выступает в роли посредника между внешним кодом и переменной name.

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

Person person = new Person(); Console.WriteLine(person.Age); // 1 // изменяем значение свойства person.Age = 37; Console.WriteLine(person.Age); // 37 // пробуем передать недопустимое значение person.Age = -23; // Возраст должен быть в диапазоне от 1 до 120 Console.WriteLine(person.Age); // 37 - возраст не изменился class Person < int age = 1; public int Age < set < if (value < 1 || value >120) Console.WriteLine("Возраст должен быть в диапазоне от 1 до 120"); else age = value; > get < return age; >> >

В данном случае переменная age хранит возраст пользователя. Напрямую мы не можем обратиться к этой переменной — только через свойство Age. Причем в блоке set мы устанавливаем значение, если оно соответствует некоторому разумному диапазону. Поэтому при передаче свойству Age значения, которое не входит в этот диапазон, значение переменной не будет изменяться:

person.Age = -23;
Консольный вывод программы:

1 37 Возраст должен быть в диапазоне от 1 до 120 37

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

Свойства только для чтения и записи

Блоки set и get не обязательно одновременно должны присутствовать в свойстве. Если свойство определяет только блок get , то такое свойство доступно только для чтения — мы можем получить его значение, но не установить.

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

Person person = new Person(); // свойство для чтения - можно получить значение Console.WriteLine(person.Name); // Tom // но нельзя установить // person.Name = "Bob"; // ! Ошибка // свойство для записи - можно устновить значение person.Age = 37; // но нелзя получить // Console.WriteLine(person.Age); // ! Ошибка person.Print(); class Person < string name = "Tom"; int age = 1; // свойство только для записи public int Age < set < age = value; >> // свойство только для чтения public string Name < get < return name; >> public void Print()=> Console.WriteLine($"Name: Age: "); >

Здесь свойство Name доступно только для чтения, поскольку оно имеет только блок get :

public string Name < get < return name; >>

Мы можем получить его значение, но НЕ можем установить:

Console.WriteLine(person.Name); // получить можно person.Name = "Bob"; // ! Ошибка - установить нельзя

А свойство Age, наоборот, доступно только для записи, поскольку оно имеет только блок set :

public int Age < set < age = value; >>

Можно установить его значение, но нельзя получить:

person.Age = 37; // установить можно Console.WriteLine(person.Age); // ! Ошибка - получить значение нельзя

Вычисляемые свойства

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

Person tom = new("Tom", "Smith"); Console.WriteLine(tom.Name); // Tom Smith class Person < string firstName; string lastName; public string Name < get < return $""; > > public Person(string firstName, string lastName) < this.firstName = firstName; this.lastName = lastName; >>

В данном случае класс Person имеет свойство Name, которое доступно только для чтения и которое возвращает общее значение на основе значений переменных firstName и lastName.

Модификаторы доступа

Мы можем применять модификаторы доступа не только ко всему свойству, но и к отдельным блокам get и set:

Person tom = new("Tom"); // Ошибка - set объявлен с модификатором private //tom.Name = "Bob"; Console.WriteLine(tom.Name); // Tom class Person < string name = ""; public string Name < get < return name; >private set < name = value; >> public Person(string name) => Name = name; >

Теперь закрытый блок set мы сможем использовать только в данном классе — в его методах, свойствах, конструкторе, но никак не в другом классе:

При использовании модификаторов в свойствах следует учитывать ряд ограничений:

  • Модификатор для блока set или get можно установить, если свойство имеет оба блока (и set, и get)
  • Только один блок set или get может иметь модификатор доступа, но не оба сразу
  • Модификатор доступа блока set или get должен быть более ограничивающим, чем модификатор доступа свойства. Например, если свойство имеет модификатор public, то блок set/get может иметь только модификаторы protected internal, internal, protected, private protected и private

Автоматические свойства

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

class Person < public string Name < get; set; >public int Age < get; set; >public Person(string name, int age) < Name = name; Age = age; >>

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

В чем преимущество автосвойств, если по сути они просто обращаются к автоматически создаваемой переменной, почему бы напрямую не обратиться к переменной без автосвойств? Дело в том, что в любой момент времени при необходимости мы можем развернуть автосвойство в обычное свойство, добавить в него какую-то определенную логику.

Стоит учитывать, что нельзя создать автоматическое свойство только для записи, как в случае со стандартными свойствами.

Автосвойствам можно присвоить значения по умолчанию (инициализация автосвойств):

Person tom = new(); Console.WriteLine(tom.Name); // Tom Console.WriteLine(tom.Age); // 37 class Person < public string Name < get; set; >= "Tom"; public int Age < get; set; >= 37; >

И если мы не укажем для объекта Person значения свойств Name и Age, то будут действовать значения по умолчанию.

Автосвойства также могут иметь модификаторы доступа:

class Person < public string Name < private set; get;>public Person(string name) => Name = name; >

Мы можем убрать блок set и сделать автосвойство доступным только для чтения. В этом случае для хранения значения этого свойства для него неявно будет создаваться поле с модификатором readonly, поэтому следует учитывать, что подобные get-свойства можно установить либо из конструктора класса, как в примере выше, либо при инициализации свойства:

class Person < // через инициализацию свойства public string Name < get; >= "Tom"; // через конструктор public Person(string name) => Name = name; >

Блок init

Начиная с версии C# 9.0 сеттеры в свойствах могут определяться с помощью оператора init (от слова «инициализация» — это есть блок init призван инициализировать свойство). Для установки значений свойств с init можно использовать только инициализатор, либо конструктор, либо при объявлении указать для него значение. После инициализации значений подобных свойств их значения изменить нельзя — они доступны только для чтения. В этом плане init-свойства сближаются со свойствами для чтения. Разница состоит в том, что init-свойства мы также можем установить в инициализаторе (свойства для чтения установить в инициализаторе нельзя). Например:

Person person = new(); //person.Name = "Bob"; //! Ошибка - после инициализации изменить значение нельзя Console.WriteLine(person.Name); // Undefined public class Person < public string Name < get; init; >= "Undefined"; >

В данном случае класс Person для свойства Name вместо сеттера использует оператор init . В итоге на строке

Person person = new();

предполагается создание объекта с инициализацией всех его свойств. В данном случае свойство Name получит в качестве значения строку «Undefined». Однако поскольку инициализация свойства уже произошла, то на строке

person.Name = "Bob"; // Ошибка

мы получим ошибку.

Как можно установить подобное свойство? Выше продемонстрирован один из способов — установка значения при определении свойства. Второй способ — через конструктор:

Person person = new("Tom"); Console.WriteLine(person.Name); // Tom public class Person < public Person(string name) =>Name = name; public string Name < get; init; >>

Третий способ — через инициализатор:

Person person = new() < Name = "Bob">; Console.WriteLine(person.Name); // Bob public class Person < public string Name < get; init; >= ""; >

В принцпе есть еще четвертый способ — установка через другое свойство с модификатором init :

var person = new Person() < Name = "Sam" >; Console.WriteLine(person.Name); // Sam Console.WriteLine(person.Email); // Sam@gmail.com public class Person < string name = ""; public string Name < get < return name; >init < name = value; Email = $"@gmail.com"; > > public string Email < get; init; >= ""; >

В данном случае свойство Name управляет полем для чтения name . Благодаря этому перед установкой значения свойства мы можем произвести некоторую предобработку. Кроме того, в выражении init устанавливается другое init-свойство — Email, которое для установки значения использует значение свойства Name — из имени получаем значение для электронного адреса.

Причем если при объявлении свойства указано значение, то в конструкторе мы можем его изменить. Значение, установленное в конструкторе, можно изменить в инициализаторе. Однако дальше процесс инициализации заканчивается. И значение не может быть изменено.

Сокращенная запись свойств

Как и методы, мы можем сокращать определения свойств. Поскольку блоки get и set представляют специальные методы, то как и обычные методы, если они содержат одну инструкцию, то мы их можем сократить с помощью оператора => :

class Person < string name; public string Name < get =>name; set => name = value; > >

Также можно сокращать все свойство в целом:

class Person < string name; // эквивалентно public string Name < get < return name; >> public string Name => name; >

модификатор required

Модификатор required (добавлен в C# 11) указывает, что поле или свойства с этим модификатором обязательно должны быть инициализированы. Например, в следующем примере мы получим ошибку:

Person tom = new Person(); // ошибка - свойства Name и Age не инициализированы public class Person < public required string Name < get; set; >public required int Age < get; set; >>

Здесь свойства Name и Age отмечены как обязательные для инициализации с помощью модификатора required , поэтому необходимо использовать инициализатор для их инициализации:

Person tom = new Person < Name = "Tom", Age = 38 >; // ошибки нет

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

Person bob = new Person("Bob"); // ошибка - свойства Name и Age все равно надо установить в инициализаторе public class Person < public Person(string name) < Name = name; >public required string Name < get; set; >public required int Age < get; set; >= 22; >

Для чего нужны get и set? [дубликат]

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

getField(); setField(value); 

работали они примерно следующим образом:

class SomeClass < . private int _value; . public int getValue() < return _value; >. public void setValue(int value) < this._value = value >= 0 ? value : 0;// таким образом не допускали ввода отрицательного значения > . > 

в С# решили упростить это действие введя геттер — get<> , и сеттер set<> для свойств

. public int Value < get < return _value; >set < this._value = value >=0 ? value : 0; > > . 

Таким образом вы можете полностью контролировать операции получения каких-то свойств или их изменения:

  • Контролировать изменяемые значения
  • Выбрасывать исключения
  • Вызывать события
  • . да всё что душе угодно

Более интересный пример:

class Light < private bool _isOn = false; private bool _isOff = true; public bool ON < get < return _isOn; >set < _isOn = value; _isOff = !value; >> public bool OFF < get < return _isOff; >set < _isOff = value; _isOn = !value; >> > 

Но на самом деле компилятор всё равно преобразовывает эти действия в методы: get_Value(); и set_Value(int value); (не помню точный синтаксис преобразования)

Где-то читал, что Джефри Рихтер критикует эту фичу C#, т.к. это всего лиш синтаксический сахар

«Лично мне свойства не нравятся, и я был бы рад, если бы их поддержку убрали из Microsoft .NET Framework и сопутствующих языков программирования. Причина в том, что свойства выглядят как поля, на самом деле являясь методами.» пруф.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *