Для чего нужны get и set? C#
Сколько читаю про них, все не могу понять как они работают и для чего нужны.
9th Aug 2019, 2:02 PM
4 Answer s
они нужны для получения скрытых переменных в классе Пример: class Test < private _x = 100; public x < get < return _x; >set < _x = value; >> > _x Скрытая переменная для других классов, но её можно получить используя доступную переменную x, при её вызове(то есть получении, пример: Console.WriteLine(Test.x))она будет возвращать значение не своё, а значение, которое вы задали в Get, тоесть значение переменной _x, также при присвоении значения переменной x, значение будет присваиваться переменной указаной в set, тоесть у нас это _x. значение value в set блоке это значение полученное при присвоении.
11th Aug 2019, 1:32 PM
да, я вам показал как используется на простом примере же. тоесть использовать можно и по другому, где это не будет легче, к примеру у вас есть класс с переменной x, но вы не хотите чтобы код мог присваивать значение переменной, а только мог получать, вы можете объявить только Get, тоесть присваивать значение переменной x нельзя будет, можно будет только получать, без get и set это невозможно, вот вам и функционал Get, set. class Test < private _x = 100 public x < get < return _x; >> > вот это код без использования set, теперь пользователь не сможет присваивать значение(то есть не сможет делать: Test.x = 50; к примеру), но он сможет получать значение (Console.WriteLine(Test.x))
11th Aug 2019, 1:39 PM
А не легче объявить переменную как public?
11th Aug 2019, 1:34 PM
А понял, спасибо за пример)
11th Aug 2019, 1:45 PM
Often have questions like this?
Learn more efficiently, for free:
Get set c что это
такой же пример только с переносом скобок
class Book
<
public string Name
<
get
<
return «Hello» ;
>
>
>
Автоматическое свойство класса
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
<
class Book
<
// свойство класса
public string Name < get ; set ; >
>
class Program
<
static void Main( string [] args)
<
Book book = new Book();
// устанавливаем значение
book.Name = «Hello» ; // будет вызвано свойство set
// получаем значение
string s = book.Name; // будет вызвано свойство get
>
>
>
В классе Book есть закрытое поле _myPrice , которое не может быть меньше 0 и больше 1000.
Для управления доступом к этому полю будет использовано свойство MyPrice
class Book
<
private int _myPrice;
// get set attributes
public int MyPrice
<
get < return _myPrice; >
set
<
if (value < 0)
_myPrice = 0;
else if (value > 1000)
_myPrice = 1000;
else
_myPrice = value;
>
>
>
class Program
<
static void Main( string [] args)
<
Book book = new Book();
book.MyPrice = 1200;
Console .WriteLine(book.MyPrice);
>
>
Результат примера

Зачем нужно использовать get set?
Если бы сделали поле _myPrice открытым и не использовали ни методы, ни свойство для доступа, мы могли бы записать в это поле любое значение, в том числе и некорректное, а так мы можем контролировать чтение и запись.
Автоматические свойства
Автоматическое свойство – это очень простое свойство, которое, в отличии от обычного свойства, уже определяет место в памяти.
class Book
<
public int Price
>
class Program
<
static void Main( string [] args)
<
Book book = new Book();
book.Price = 1200;
Console .WriteLine(book.Price);
>
>
Результат примера

Инициализация автоматических свойств
Начиная с версии C# 6.0 добавлена функциональность для инициализации автосвойств.
class Book
<
public String Name < get; >= «Dragon» ; // инициализация автосвойства
public String Author < get; set; >= «Gari» ; // инициализация автосвойства
>
class Program
<
static void Main( string [] args)
<
Book book = new Book();
Console .WriteLine(book.Name); // «Dragon»
Console .WriteLine(book.Author); // «Gari»
>
>
Свойства в C#: назначение, использование, примеры

В статье поговорим о свойствах полей класса ( c# get set ). Разберемся с определением и назначением этой структуры, а также рассмотрим примеры внедрения этой концепции в C#-приложения.
Професійний курс від mate.academy: Java.
Погрузьтеся у світ програмування.
Что такое свойство в C#?
Свойство в C# является членом класса, который используется для установки и получения данных из поля данных класса. Самый важный момент, о котором нужно помнить — свойство в C# никогда не используется для хранения данных, оно действует как интерфейс для их передачи. Это своего рода расширение переменных класса, предоставляющее возможность читать, записывать или изменять значения этих переменных, не влияя на внешний способ доступа к ним в приложении.
Оно содержит один или два блока кода, называемых аксессорами, внутри которых находятся методы доступа get и set . Используя эти методы, мы можем изменить внутреннюю реализацию переменных класса в зависимости от наших требований.
Записываются свойства ( property ) так:
Експертний курс від laba: Business English for HR.
Мова бізнесу для HR-професіоналів.
При написании свойств важно определиться с модификатором и типом возвращаемого значения, чтобы внести необходимые изменения в переменные класса (исходя из того, что нам требуется).
В такой конструкции код в методе get будет выполняться всякий раз, когда свойство читается (возвращает результат), а код в методе set будет отрабатывать, когда свойство переопределяется другим значением.
Такая структура данных в С#, подразделяются на три типа:
-
Read-Write (для чтения-записи). Так называется свойство, содержащее два блока аксессора.
Также следует помнить, что свойства не принимают никаких параметров, а тип данных свойств должен быть таким же, как у полей, для которых мы его создаем.
Вот простейший пример определения приватной переменной со свойством:
class Item < private string color; public string Color < get < return color; >set < color = value; >> >
Здесь мы написали свойство «Color» с методами get (для возврата значения) и set (для его переопределения).
Освітній курс від robotdreams: Аналітик даних.
Перетворюйте дані на рішення.
Сразу отметим, что в методе get мы либо возвращаем, либо вычисляем, а затем возвращаем значение поля. Но тут важно понимать, что акссесор не используется для изменения состояния объекта! С помощью методов get и set можно лишь расширить поведение переменных:
class User < private string fullname = "Sheldon Cooper"; public string FullName< get< return fullname.ToUpper(); >set < if (value == "Sheldon Cooper") fullname = value; >> >
В примере рассмотрено написание частной переменной fullname и ее свойства Fullname . Их названия одинаковы, если не считать регистра, но это просто стиль написания. В своих примерах вы можете называть их по-разному, их названия могут быть какие угодно. Параметр value служит для определения передаваемого значения.
Таким образом применение концепции свойств дает полный контроль над доступом к полям класса.
Вот как это выглядит:
User u = new User(); u.Fullname = "Howard Wolowitz"; // срабатывает аксессор set Console.WriteLine(u.Fullname); // срабатывает аксессор get
Здесь мы наделяем наше свойство новым значением с вызовом set , а get сработает когда мы попытаемся прочитать это значение.
Преимущества применения такой концепции
Вы можете задаться вопросом: для чего так необходимы эти свойства? Ведь в подобных ситуациях можно обойтись обыкновенными переменными класса. Вся суть концепции свойств заключается в возможности вкладывания в переменные дополнительной логики.
Например, при присваивании ей другого значения:
class Human < private int years; public int Years< set< if(value < 18)< Console.WriteLine("Доступ только совершеннолетним!"); >else < years = value; >> get > >
Имей переменная years из нашего примера public-доступ — у разработчика появилась бы возможность присвоить ей извне другое значение, что не всегда хорошо (подобные вещи чаще всего происходят в результате ошибки или случайности). В таких ситуациях нам и необходимы свойства , ограничивающие к ней доступ.
А еще, применяя свойства, мы:
-
получаем универсальный инструмент для работы с полями и их доступностью извне;
Ефективний курс від laba: Фінансовий менеджер.
Оптимізуйте фінансовий розвиток компанії.
Read-Write
Рассмотрим пример реализации класса Exmpl с одним целочисленным полем, используемым в качестве хранилища для свойства Numb , обеспечивающего реализацию стандартных методов-аксессоров.
using System; class Exmpl < int _numb; public int Numb< get< return this._numb; >set < this._numb = value; >> > class Prog < static void Main()< Exmpl exmpl = new Exmpl(); exmpl.Numb = 5; // set < >Console.WriteLine(example.Numb); // get < >> >
Выведет:5
Влияние модификаторов доступности свойств на переменные
Для использования нашего свойства необходимо объявить его открытым (public). Иначе нам не удастся получить к нему доступ и результатом будет ошибка компилятора. Также можно использовать модификаторы отдельно во внутренних блоках свойства.
Однако тут мы должны помнить о ряде существующих ограничений:
- Установка модификатора в блоках аксессоров возможна, когда у свойства есть оба блока.
- Только одному из двух блоков можно написать модификатор — не двум сразу
- Модификаторы внутренних блоков должны иметь более жесткое ограничение доступности, в отличие от модификатора самого свойства. Например, при открытом свойстве (public) его внутренние блоки могут быть: protected , private , internal , protected internal .
Свойства и массив double
Рассмотрим пример по реализации свойства double-массива. Объявим:
- поле X — числовой массив
- несколько конструкторов класса;
- индексатор, возвращающий нужные нам члены массива по порядковому номеру;
- свойство Summ
namespace Highload < class ArrDouble< double[] X; // массив public ArrDouble(int size)< // выделение ячейки памяти нашему массиву X = new double[size]; for (int i = 0; i < size; i++) X[i] = 0.0; >// заполнение массива нулевыми значениями public ArrDouble(double[] _X) < X = new double[_X.Length]; // копируем массив for (int i = 0; i < _X.Length; i++) X[i] = _X[i]; >public double this[int index]< get< if ((index >= 0) && (index < X.Length)) return X[index]; else return 0.0; >> // индексация */Объявление свойства Summary c методом get, находящим сумму всех членов массива и set, раздающим этим членам значения/* public double Summary < get< // суммируем элементы double summ = 0; for (int i = 0; i < X.Length; i++) summ += X[i]; return summ; >set < // Равномерное распределение значений между членами массива double val = value/X.Length; for (int i = 0; i < X.Length; i++) X[i] = val; >> > class Prog < static void Main(string[] args) < double[] X = < 1.0, 2.5, 2.0, 4.5, 0.0 >; ArrDouble ad = new ArrDouble(X); // создание экземпляра ArrDouble double summary; summ = ad.Summ; Console.WriteLine("summ = ", summ); // заполняем ad единицами ad.Summ = 1.0 * X.Length; // проверяем double test; test = ad[2]; // test = 1.0 Console.WriteLine("test= ", test); > > >
Выведет:
summ = 10
test = 1
В Summary get вычисляет сумму всех членов массива, а set — раздает им значение.
Создание свойства Read-only
Мы рассмотрели ранее, что свойство с одним методом get принадлежит типу read-only . Приведем пример создания такого рода свойств:
using System; namespace Highload < class Human< private string fullname; private string loc; public Human(string a, string b)< fullname = a; loc = b; >public string FullName < get< return fullname; >> public string Loc < get< return loc; >> > class Prog < static void Main(string[] args)< Human u = new Human("Sheldon Cooper", "Pasadena"); // ошибка, которую выдаст компилятор // u.FullName = "Howard Wolowitz"; // get accessor will invoke Console.WriteLine("FullName: " + u.FullName); // get accessor will invoke Console.WriteLine("Loc: " + u.Loc); >> >
Здесь мы применили только один метод доступа — get , сделав тем самым наше свойство доступным только для чтения. Раскомментировав закомментированный код, мы получим ошибку компиляции из-за отсутствия возможности установить новое значение при помощи set .
Запустив нашу программу, мы получим следующий результат:
Name: Sheldon Cooper
Loc: Pasadena
Создание свойства write-only
using System; namespace Highload < class Pers< private string fullname; public string FullName< set< fullname = value; >> private string loc; public string Loc < set< loc = value; >> public void GetPersonDetails() < Console.WriteLine("FullName: " + fullname); Console.WriteLine("Loc: " + loc); >> class Prog < static void Main(string[] args)< Pers u = new Pers(); u.FullName = "Sheldon Cooper"; u.Loc = "Pasadena"; // компилятор выдаст ошибку //Console.WriteLine(u.FullName); u.GetPersonDetails(); >> >
Здесь, наоборот, мы применили только один метод — set , сделав свойство Write-only . А раскомментировав ранее закомментированный код, мы получим ошибку компиляции из-за отсутствия возможности возврата значения.
Результат программы будет такой же, как и в предыдущем примере.
Автоматически реализуемые свойства
Свойства управляют доступностью переменных класса, и если такая переменная одна — тогда все понятно. Но что если у нас их несколько десятков? Ведь в таком случае писать каждой однотипное свойство — долго и затратно. Для решения такого рода вопросов в C# , а точнее в его фреймворк .NET, был добавлен функционал реализации автоматических свойств. Давайте разберемся, что это такое.
Автоматическим называется свойство, содержащее стандартные методы доступа ( get, set ) без какой-либо логической реализации, например:
using System; namespace Highload < class Pers< public string FullName < get; set; >public string Loc < get; set; >> class Prog < static void Main(string[] args)< Pers u = new Pers(); u.FullName = "Sheldon Cooper"; u.Loc = "Pasadena"; Console.WriteLine("FullName: " + u.FullName); Console.WriteLine("Loc: " + u.Loc); >> >
Такой подход уменьшает объем написанного кода. При применении автоматических свойств компилятор С# неявно создает частное, анонимное поле за кулисами для получения данных.
Структурная переменная и доступ к ней (пример)
Рассмотрим принцип работы связки свойств и структурной переменной типа fraction , реализующей дробь:
using System; namespace Highload < struct Frctn< public int nume; // numerator public int deno; // denominator >// класс комплексного числа class ComplexNumber < private Frctn real; private Frctn im; // несколько конструкторов public ComplexNumber(int _real, int _im)< real.nume = _real; real.deno = 1; im.nume = _im; im.deno = 1; >public ComplexNumber(Frctn _real, Frctn _im) < real = _real; im = _im; >// свойство действительной части public Frctn Real < get< return real; >set < real = value; >> // свойство мнимой части public Frctn Im < get< return im; >set < im = value; >> public double RealD < get< return (double)real.nume/(double)real.deno; >> public double ImD < get< return (double)im.nume / (double)im.deno; >> // свойство, возвращающее модуль этого числа public double Ab < get< double x,y,z; x = real.nume / (double)real.deno; y = im.nume / (double)im.deno; z = Math.Sqrt(y * y + x * x); return z; >> > class Prog< static void Main(string[] args)< Frctn r = new Frctn(); Frctn i = new Frctn(); r.nume = 3; r.deno = 1; i.nume = 4; i.deno = 1; ComplexNumber c = new ComplexNumber(x, y); // экземпляр класса ComplexNumber // свойства класса ComplexNumber double ab = c.Ab; // берем модуль, ab = 5 Console.WriteLine("Ab = ", ab); double rd, id; rd = c.RealD; // rd = 3/1 = 3.0 // = 4.0 Console.WriteLine("rd = ", rd); // свойство Real Frctn R = new Fraction(); R = c.Real; // R = < 3, 1 >Console.Write("R.nume = , ", R.nume); Console.WriteLine("R.deno = ", R.deno); > > >
Ab = 5
rd = 3
R.nume = 3, R.deno = 1
Рассматривая свойства, надо отметить, что они не добавляют место в памяти для переменных класса, а только контролируют доступ к ним. А также не являются членами данных класса, а переменные определяются независимо от них.
Обзор рассматриваемой концепции
Давайте кратко перечислим наиболее важные моменты, которые необходимо четко понимать при работе со свойствами:
- Свойства разработаны для контроля доступности внутренних полей класса
- Аксессор get нужен для возврата значения свойства, а set — для переопределения этого значения.
- value — ключевое слово в set -аксессоре, используемое для назначения ему значения
- C#-свойства делятся на категории:
- Read-Write (чтение запись) с двумя аксессорами внутри
- Read only (только для чтения) — отсутствует метод set
- Write only (только для записи) — отсутствует метод get
Для лучшего восприятия и освоения рассматриваемой концепции предлагаю посмотреть видеоролик по теме:
Свойства — геттеры и сеттеры
Первый тип это свойства-данные (data properties). Мы уже знаем, как работать с ними. Все свойства, которые мы использовали до текущего момента, были свойствами-данными.
Второй тип свойств мы ещё не рассматривали. Это свойства-аксессоры (accessor properties). По своей сути это функции, которые используются для присвоения и получения значения, но во внешнем коде они выглядят как обычные свойства объекта.
Геттеры и сеттеры
Свойства-аксессоры представлены методами: «геттер» – для чтения и «сеттер» – для записи. При литеральном объявлении объекта они обозначаются get и set :
let obj = < get propName() < // геттер, срабатывает при чтении obj.propName >, set propName(value) < // сеттер, срабатывает при записи obj.propName = value >>;
Геттер срабатывает, когда obj.propName читается, сеттер – когда значение присваивается.
Например, у нас есть объект user со свойствами name и surname :
let user = < name: "John", surname: "Smith" >;
А теперь добавим свойство объекта fullName для полного имени, которое в нашем случае «John Smith» . Само собой, мы не хотим дублировать уже имеющуюся информацию, так что реализуем его при помощи аксессора:
let user = < name: "John", surname: "Smith", get fullName() < return `$$`; > >; alert(user.fullName); // John Smith
Снаружи свойство-аксессор выглядит как обычное свойство. В этом и заключается смысл свойств-аксессоров. Мы не вызываем user.fullName как функцию, а читаем как обычное свойство: геттер выполнит всю работу за кулисами.
На данный момент у fullName есть только геттер. Если мы попытаемся назначить user.fullName= , произойдёт ошибка:
let user = < get fullName() < return `. `; >>; user.fullName = "Тест"; // Ошибка (у свойства есть только геттер)
Давайте исправим это, добавив сеттер для user.fullName :
let user = < name: "John", surname: "Smith", get fullName() < return `$$`; >, set fullName(value) < [this.name, this.surname] = value.split(" "); >>; // set fullName запустится с данным значением user.fullName = "Alice Cooper"; alert(user.name); // Alice alert(user.surname); // Cooper
В итоге мы получили «виртуальное» свойство fullName . Его можно прочитать и изменить.
Дескрипторы свойств доступа
Дескрипторы свойств-аксессоров отличаются от «обычных» свойств-данных.
Свойства-аксессоры не имеют value и writable , но взамен предлагают функции get и set .
То есть, дескриптор аксессора может иметь:
- get – функция без аргументов, которая сработает при чтении свойства,
- set – функция, принимающая один аргумент, вызываемая при присвоении свойства,
- enumerable – то же самое, что и для свойств-данных,
- configurable – то же самое, что и для свойств-данных.
Например, для создания аксессора fullName при помощи defineProperty мы можем передать дескриптор с использованием get и set :
let user = < name: "John", surname: "Smith" >; Object.defineProperty(user, 'fullName', < get() < return `$$`; >, set(value) < [this.name, this.surname] = value.split(" "); >>); alert(user.fullName); // John Smith for(let key in user) alert(key); // name, surname
Ещё раз заметим, что свойство объекта может быть либо свойством-аксессором (с методами get/set ), либо свойством-данным (со значением value ).
При попытке указать и get , и value в одном дескрипторе будет ошибка:
// Error: Invalid property descriptor. Object.defineProperty(<>, 'prop', < get() < return 1 >, value: 2 >);
Умные геттеры/сеттеры
Геттеры/сеттеры можно использовать как обёртки над «реальными» значениями свойств, чтобы получить больше контроля над операциями с ними.
Например, если мы хотим запретить устанавливать короткое имя для user , мы можем использовать сеттер name для проверки, а само значение хранить в отдельном свойстве _name :
let user = < get name() < return this._name; >, set name(value) < if (value.length < 4) < alert("Имя слишком короткое, должно быть более 4 символов"); return; >this._name = value; > >; user.name = "Pete"; alert(user.name); // Pete user.name = ""; // Имя слишком короткое.
Таким образом, само имя хранится в _name , доступ к которому производится через геттер и сеттер.
Технически, внешний код всё ещё может получить доступ к имени напрямую с помощью user._name , но существует широко известное соглашение о том, что свойства, которые начинаются с символа «_» , являются внутренними, и к ним не следует обращаться из-за пределов объекта.
Использование для совместимости
У аксессоров есть интересная область применения – они позволяют в любой момент взять «обычное» свойство и изменить его поведение, поменяв на геттер и сеттер.
Например, представим, что мы начали реализовывать объект user , используя свойства-данные имя name и возраст age :
function User(name, age) < this.name = name; this.age = age; >let john = new User("John", 25); alert( john.age ); // 25
…Но рано или поздно всё может измениться. Взамен возраста age мы можем решить хранить дату рождения birthday , потому что так более точно и удобно:
function User(name, birthday) < this.name = name; this.birthday = birthday; >let john = new User("John", new Date(1992, 6, 1));
Что нам делать со старым кодом, который использует свойство age ?
Мы можем попытаться найти все такие места и изменить их, но это отнимает время и может быть невыполнимо, если код используется другими людьми. И кроме того, age – это отличное свойство для user , верно?
Давайте его сохраним.
Добавление геттера для age решит проблему:
function User(name, birthday) < this.name = name; this.birthday = birthday; // возраст рассчитывается из текущей даты и дня рождения Object.defineProperty(this, "age", < get() < let todayYear = new Date().getFullYear(); return todayYear - this.birthday.getFullYear(); >>); > let john = new User("John", new Date(1992, 6, 1)); alert( john.birthday ); // доступен как день рождения alert( john.age ); // . так и возраст
Теперь старый код тоже работает, и у нас есть отличное дополнительное свойство!