Що таке {get; набір; } синтаксис в C #?


577

Я вивчаю ASP.NET MVC і можу читати англійські документи, але я не дуже розумію, що відбувається в цьому коді:

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

Що це означає { get; set; }:?


4
Загалом пам’ятайте - сетери роблять ваш об’єкт змінним, погана ідея. Геттери порушують "Скажіть об'єкту, що робити, не вимагайте його інформації та маніпулюйте нею самостійно". Так що, як правило, не додайте сетерів та getters за замовчуванням Вони вам знадобляться часто, але ви завжди повинні знайти справжню потребу, перш ніж додавати їх. Зокрема, сеттери майже ніколи не повинні використовуватися у виробничому коді (Прагніть до незміненості, де це можливо, і коли потрібна мутація, вам слід попросити його мутувати, а не встановлювати значення).
Білл К

8
Просто додати щось ... Якщо ви не ставите, {get; set;}ви створюєте поле, але якщо ставите, {get; set;}ви створюєте властивість . Наявність властивості може полегшити деякі речі, особливо під час роботи з Reflection.
Сейчі

@Seichi за допомогою get-setter також створює поле, але це приховано, оголошено приватним та модифіковане властивостями, створеними автоматично; все це зроблено компілятором.
Джонатан Рамос

1
чи не власні властивості перемагають призначення приватних полів?
mireazma

Відповіді:


567

Це так звана властивість авто, і по суті це скорочення для наступного (аналогічний код буде створений компілятором):

private string name;
public string Name
{
    get
    {
        return this.name;
    }
    set
    {
        this.name = value;
    }
}

93
Клаус, чи можете ви пояснити, що буде з цим кодом? Це могло б отримати користь від більш ретельного пояснення.
TylerH

3
Тож, щоб бути впевненим: це як би я перевантажив =оператора, але тільки для одного конкретного елемента, правда?
Привіт-Ангел

9
Навіщо нам потрібен приватний вар. : - / сором.
Олівер Діксон

2
@TylerH Причиною приватної змінної є інкапсуляція, get / set забезпечує "ворота" для отримання або встановлення змінної. Хоча є багато причин не використовувати get / setters, оскільки "ворота" можуть порушити інкапсуляцію приватної змінної. (це не повинно бути доступним)
Олександр

4
Це може бути очевидним, але я хочу уточнити, що стенограма не є для цього буквально стенограмою. Тобто, приватна змінна nameне створюється. Якщо ви спробували посилатися на цю приватну змінну в класі, вона не вдасться. Я не впевнений, як це робить C #, але він поводиться так, ніби є приватна змінна без імені, до якої ви не можете отримати доступ у своєму коді.
Дензілое

432

Тож, як я розумію, це { get; set; }"авто властивість", як і @Klaus та @Brandon, це стенограма для написання властивості з "полем резервного копіювання". Отже, у цьому випадку:

public class Genre
{
    private string name; // This is the backing field
    public string Name   // This is your property
    {
        get => name;
        set => name = value;
    }
}

Однак якщо ти схожий на мене - приблизно годину або близько тому - ти насправді не розумієш, що таке властивості та аксесуари , і ти не маєш найкращого розуміння деяких базових термінологій. MSDN - це чудовий інструмент для вивчення таких предметів, але це не завжди легко зрозуміти для початківців. Тому я спробую тут пояснити це більш поглиблено.

getі setє аксесуарами , тобто вони можуть отримати доступ до даних та інформації в приватних полях (як правило, із резервного поля ), і зазвичай це роблять із загальнодоступних властивостей (як ви бачите в наведеному вище прикладі).

Не можна заперечувати, що наведене твердження є досить заплутаним, тому давайте перейдемо до деяких прикладів. Скажімо, цей код стосується жанрів музики. Тож у класі Жанр ми хочемо отримати різні жанри музики. Скажімо, ми хочемо мати 3 жанри: хіп-хоп, рок та кантрі. Для цього ми б використали ім’я Класу для створення нових примірників цього класу.

Genre g1 = new Genre(); //Here we're creating a new instance of the class "Genre"
                        //called g1. We'll create as many as we need (3)
Genre g2 = new Genre();
Genre g3 = new Genre();

//Note the () following new Genre. I believe that's essential since we're creating a
//new instance of a class (Like I said, I'm a beginner so I can't tell you exactly why
//it's there but I do know it's essential)

Тепер, коли ми створили екземпляри класу жанру, ми можемо встановити імена жанрів за допомогою властивості 'Name', яке було встановлено вище.

public string Name //Again, this is the 'Name' property
{ get; set; } //And this is the shorthand version the process we're doing right now 

Ми можемо встановити ім'я 'g1' на Hip Hop, написавши наступне

g1.Name = "Hip Hop";

Те, що відбувається тут, начебто складне. Як я вже говорив раніше, getі setотримуйте доступ до інформації з приватних полів, до яких ви інакше не зможете отримати доступ. getможе лише читати інформацію з цього приватного поля та повертати її. setможе записувати інформацію лише в цьому приватному полі. Але маючи властивість з обома getі setми можемо виконувати обидві ці функції. І, пишучи, g1.Name = "Hip Hop";ми спеціально використовуємо setфункцію з власності Name

setвикористовує неявну змінну, що називається value. В основному, що це означає, що коли ви бачите "значення" всередині set, воно посилається на змінну; змінна "значення". Коли ми пишемо, g1.Name =ми використовуємо =передати valueзмінну, яка в даному випадку є "Hip Hop". Таким чином, ви можете подумати про це так:

public class g1 //We've created an instance of the Genre Class called "g1"
{
    private string name;
    public string Name
    {
        get => name;
        set => name = "Hip Hop"; //instead of 'value', "Hip Hop" is written because 
                              //'value' in 'g1' was set to "Hip Hop" by previously
                              //writing 'g1.Name = "Hip Hop"'
    }
}

Важливо зазначити, що наведений вище приклад насправді не записаний у коді. Це більше гіпотетичний код, який представляє те, що відбувається на задньому плані.

Отже, тепер, коли ми встановили ім'я g1 екземпляр жанру , я вважаю, що ми можемо отримати ім'я, написавши

console.WriteLine (g1.Name); //This uses the 'get' function from our 'Name' Property 
                             //and returns the field 'name' which we just set to
                             //"Hip Hop"

і якби ми запустили це, ми потрапили б "Hip Hop"у свою консоль.

Тож для цього пояснення я докладу і приклад із результатами

using System;
public class Genre
{
    public string Name { get; set; }
}

public class MainClass
{
    public static void Main()
    {
        Genre g1 = new Genre();
        Genre g2 = new Genre();
        Genre g3 = new Genre();

        g1.Name = "Hip Hop";
        g2.Name = "Rock";
        g3.Name = "Country";

        Console.WriteLine ("Genres: {0}, {1}, {2}", g1.Name, g2.Name, g3.Name);
    }
}

Вихід:

"Genres: Hip Hop, Rock, Country"

18
Особисто я просто прокоментував би це як такеset{name = value;} // 'value' here is equal to "Hip Hop"
maksymiuk

2
@iLoveUnicorns, це там з метою абстрагування даних . Поле резервного копіювання - це те, що містить фактичні дані. Визначення властивості фактично визначає спосіб доступу до даних методами getта setметодами. Надане я посилання містить чудову цитату Джона Гуттага вгорі сторінки. Я б рекомендував прочитати його книгу або навіть пройти цей безкоштовний онлайн-курс
Джозі Томпсон

2
Ми не можемо просто використовувати: public class Genre{public string Name;} замість: public class Genre{ public string Name { get; set; }}. Я маю на увазі, навіщо нам навіть потрібно {get; набір; }?
користувач2048204

1
Здається, моя тривога вже відлунила. Якщо ви оголосите таким чином: "public string Name {get; set;}", і ви отримаєте доступ таким чином: g1.Name = "Хіп-хоп"; - то де орієнтована на об'єкт? Мені навіть не потрібне так зване "резервне поле". Що стосується мене, резервне поле навіть не існує. Тому що я отримую доступ лише до публічного поля. І якщо публічне поле є "загальнодоступним", воно не відповідає вимогам ОО. Повернемося до COBOL.
Барух Атта

1
Чудова відповідь, але якщо ми ведемо педантичність, "набір" - це мутатор, а не аксесуар.
пітланг

100

Це автоматичні властивості

В основному інший спосіб написання властивості з полем резервного копіювання.

public class Genre
{
    private string _name;

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

7
Що називається "резервним полем"?
kn3l

4
@stackunderflow: поле резервного копіювання - це місце, де зберігаються дані. (що повертається під час використання getта зберігається з використанням set). Як шафа, до якої getі setвідчиняє двері.
Грант Томас

5
@stackunderflow: У цій відповіді поле резервного копіювання _name. В автоматичному властивості поле резервного копіювання приховано.
Джастін

36

Це короткий шлях цього:

public class Genre
{
    private string _name;

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

33

Це ярлик для викриття членів даних як публічних, щоб не потрібно було чітко створювати приватних членів даних. C # буде створювати приватний член для вас.

Ви можете просто оприлюднити своїх учасників даних, не використовуючи цей ярлик, але тоді, якщо ви вирішили змінити реалізацію члена даних, щоб мати певну логіку, тоді вам потрібно буде зламати інтерфейс. Отже, коротше, це ярлик для створення більш гнучкого коду.


2
Келсі - ви могли б пояснити, як цей синтаксис робить його більш "гнучким" кодом? Я цього не бачу. Якщо ви додасте будь-яку "логіку" до сеттера або геттеру, то в ефірному випадку (з приватними даними або без них) ви все одно будете порушувати інтерфейс, як він є, і потребуєте певного кодування.
Baruch Atta

18

В основному, це ярлик:

class Genre{
    private string genre;
    public string getGenre() {
        return this.genre;
    }
    public void setGenre(string theGenre) {
        this.genre = theGenre;
    }
}
//In Main method
genre g1 = new Genre();
g1.setGenre("Female");
g1.getGenre(); //Female

5
Це не відповідає на запитання. В ОП говорили про властивості.
theB

6
Я знаю властивості Get and Set, це приклад, який допомагає зрозуміти краще
Jirson Tavera

10

1
Е ... Це означає, що ви зберігаєте нульову посилання на рядок і потім завантажуєте її значення зі стандартного місця, коли get; set;викликається?
Aurum Aquila

1
Так, вона зберігається nullяк і будь-яка stringзмінна доsomeInstanceOfGenere.Name = "someValue"
Даніель А. Білий

6

Вони є учасниками загальнодоступної власності.

Ви б використовували їх для отримання / встановлення значення цього властивості в екземплярі жанру.


6

Це властивість, реалізована автоматично. Це, в основному, скорочений спосіб створення властивостей для класу в C #, без необхідності визначати приватні змінні для них. Зазвичай вони використовуються, коли не потрібна додаткова логіка при отриманні або встановленні значення змінної.

Докладніше ви можете прочитати в Посібнику з автоматичного впровадження властивостей MSDN .


6
  • Шаблон get / set забезпечує структуру, яка дозволяє додавати логіку під час встановлення ('set') або пошуку ('get') екземпляра властивості екземпльованого класу, що може бути корисно, коли потрібна певна логіка екземплярів для власність.

  • Властивість може мати лише доступ "отримати", що робиться для того, щоб зробити цю властивість лише для читання

  • При реалізації шаблону get / set використовується проміжна змінна як контейнер, в який можна розмістити значення і витягти значення. Проміжна змінна зазвичай є префіксом підкресленням. Ця проміжна змінна є приватною для того, щоб забезпечити доступ до неї лише за допомогою викликів get / set. Дивіться відповідь Брендона, оскільки його відповідь демонструє найбільш часто використовувані синтаксичні умови для реалізації get / set.


5

Це означає, що якщо ви створите змінну типу Жанр, ви зможете отримати доступ до змінної як властивості

Genre oG = new Genre();
oG.Name = "Test";

5
Якщо ви не використовуєте автоматично реалізовані властивості, ви все одно можете отримати доступ до неї таким чином. тобто AIP - це не про доступ ззовні, а про декларування всередині класу.
абатищев

4

Такий { get; set; }синтаксис називається автоматичними властивостями, синтаксисом C # 3.0

Для компіляції ви повинні використовувати Visual C # 2008 / csc v3.5 або вище. Але ви можете скласти вихід, орієнтований на найменший рівень .NET Framework 2.0 (для підтримки цієї функції не потрібні умови виконання або класи).


4

У Visual Studio, якщо ви визначаєте властивість Xу класі та хочете використовувати цей клас лише як тип, після побудови проекту ви отримаєте попередження, яке говорить: "Поле X ніколи не призначається, і завжди буде його за замовчуванням значення " .

Додаючи { get; set; }до Xвласності, ви не отримаєте це попередження.

Крім того, у Visual Studio 2013 та версії версії, додавши { get; set; }ви можете побачити всі посилання на цей ресурс.

введіть тут опис зображення


4

Це в основному стенограма. Ви можете писати public string Name { get; set; }як у багатьох прикладах, але ви також можете написати:

private string _name;

public string Name
{
    get { return _name; }
    set { _name = value ; } // value is a special keyword here
}

Для чого він використовується? Він може використовуватися для фільтрації доступу до ресурсу, наприклад, ви не хочете, щоб імена включали номери.

Дозвольте навести приклад:

private class Person {
    private int _age;  // Person._age = 25; will throw an error
    public int Age{
        get { return _age; }  // example: Console.WriteLine(Person.Age);
        set { 
            if ( value >= 0) {
                _age = value; }  // valid example: Person.Age = 25;
        }
    }
}

Офіційно його називають "Властивості, що реалізуються автоматично", і його добра звичка читати ( керівництво з програмування ) Я також порекомендую відео з підручниками C # Properties: Навіщо використовувати "get" та "set" .


2

Установіть це модифікатори доступу до власності. Отримати зчитування поля властивості. Set встановлює значення властивості. Отримати це як доступ лише для читання. Набір - це як доступ лише для запису. Щоб використовувати властивість як read, слід використовувати як get, так і set.


1
Я думаю, що встановити не модифікатори доступу, фактично вони є аксесуарами. Модифікатори доступу такі: громадські, приватні, внутрішні тощо
Rohit Arora

1

Get викликається, коли властивість з’являється праворуч (RHS) Набір викликається, коли властивість з’являється з лівої сторони (LHS) символу '='

Для власне реалізованого властивості поле резервного копіювання працює поза сценою і не є видимим.

Приклад:

public string Log { get; set; }

Тоді як для власності, яка не реалізується автоматично, поле резервного копіювання є вперед, видно як приватна змінна область.

Приклад:

private string log;

public string Log
{
    get => log;
    set => log = value;
}

Також тут варто зазначити, що "getter" і "setter" можуть використовувати різні "поле резервного"


Схоже, це не відповідає на поставлене запитання.
TylerH

Надається підказка про те, коли викликається get & set. Усі відповіді, згадані вище, справляють враження, що поле резервного копіювання для get & set однакове. Але це не так. Тож моя відповідь дуже стосується головного питання. Сподіваюся, ви згодні зі мною.
Бала

Для властивостей, створених автоматично, про що йдеться у запитанні, не може бути різних полів резервування, використовуваних для геттера та сеттера; є лише одне резервне поле. Для неавтоматичного властивості (про яке питання не задається) може взагалі навіть не бути концепційним полем. Крім того, ви можете написати програму з геттером з лівого боку оператора присвоєння та з програмою з правого боку оператора призначення. Тож не тільки вся ця інформація не відповідає на поставлене запитання, але це все також неправильно.
Сервіс

0

Визначте приватні змінні

Всередині конструктора і завантажте дані

Я створив Constant і завантажую дані з константи в клас вибраного списку.

public  class GridModel
{
    private IEnumerable<SelectList> selectList;
    private IEnumerable<SelectList> Roles;

    public GridModel()
    {
        selectList = from PageSizes e in Enum.GetValues(typeof(PageSizes))
                       select( new SelectList()
                       {
                           Id = (int)e,
                           Name = e.ToString()
                       });

        Roles= from Userroles e in Enum.GetValues(typeof(Userroles))
               select (new SelectList()
               {
                   Id = (int)e,
                   Name = e.ToString()
               });
    }

  public IEnumerable<SelectList> Pagesizelist { get { return this.selectList; } set { this.selectList = value; } } 
  public IEnumerable<SelectList> RoleList { get { return this.Roles; } set { this.Roles = value; } }
  public IEnumerable<SelectList> StatusList { get; set; }

}

0

Властивість - це як би шар, який відокремлює приватну змінну від інших членів класу. Із зовнішнього світу відчувається, що власність - це просто поле, доступ до якого можна отримати за допомогою .Property

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName => $"{FirstName} {LastName}";
}

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName { get { return $"{FirstName} {LastName}"; } }
}

FullName - це власність. Той зі стрілкою - це ярлик. Із зовнішнього світу ми можемо отримати доступ до FullName так:

var person = new Person();
Console.WriteLine(person.FullName);

Абоненти не переймаються тим, як ви реалізували FullName. Але всередині класу ви можете змінити FullName все, що завгодно.

Перегляньте Документацію Microsoft для більш детального пояснення:

https://docs.microsoft.com/en-us/dotnet/csharp/properties

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.