Что такое {получить; набор; } синтаксис в C #?


578

Я изучаю 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
разве свойства авто не побеждают назначение частных полей?
Миреазма

Ответы:


568

Это так называемое свойство auto, которое по сути является сокращением для следующего (подобный код будет сгенерирован компилятором):

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

93
Клаус, можешь объяснить, что будет с этим кодом? Это могло бы выиграть от более подробного объяснения.
TylerH

3
Итак, просто чтобы быть уверенным: это как если бы я перегружал =оператор, но только для одного конкретного элемента, верно?
Привет, Ангел,

9
Зачем нам нужен частный вар. : - / позор.
Оливер Диксон

2
@TylerH Причиной закрытой переменной является инкапсуляция, метод get / set предоставляет «ворота» для получения или установки переменной. Хотя есть много причин не использовать get / setters, потому что «gate» может нарушить инкапсуляцию закрытой переменной. (он не должен быть доступен)
Александр

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)

Теперь, когда мы создали экземпляры класса Genre, мы можем установить названия жанров, используя свойство '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' на хип-хоп, написав следующее

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; }}. Я имею в виду, зачем нам вообще нужно набор; }?
user2048204

1
Похоже, мое беспокойство уже отражено. Если вы объявляете этот путь: «public string Name {get; set;}» и получаете доступ к этому пути: g1.Name = "Hip Hop"; - тогда где находится объектная ориентация? Мне даже не нужно так называемое «поле поддержки». Насколько мне известно, поля поддержки даже не существует. Потому что у меня есть доступ только к публичному полю. И если публичное поле является «публичным», то оно не соответствует OO. Давайте все вернемся в Кобол.
Барух Атта

1
Отличный ответ, но если мы педантичны, «сет» - это мутатор, а не аксессор.
pythlang

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
Келси - не могли бы вы объяснить, как этот синтаксис делает его более «гибким» кодом? Я этого не вижу Если вы добавите какую-либо «логику» к установщику или получателю, то в случае эфира (с частными данными или без них) вы все равно сломаете интерфейс, как он есть, и нуждаетесь в некотором кодировании.
Барух Атта

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, это пример, который помогает лучше понять
Джирсон Тавера

10

1
Эх ... Значит ли это, что вы сохраняете нулевую ссылку на строку, а затем загружаете ее значение из стандартного местоположения при get; set;вызове?
Aurum Aquila

1
Да, он хранится nullкак любая stringпеременная доsomeInstanceOfGenere.Name = "someValue"
Даниэль А. Уайт

6

Они являются доступными для имени публичной собственности.

Вы бы использовали их, чтобы получить / установить значение этого свойства в экземпляре Genre.


6

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

Вы можете прочитать больше в Руководстве по программированию автоматически реализуемых свойств MSDN .


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

  • Свойство может иметь только метод доступа get, что делается для того, чтобы сделать это свойство доступным только для чтения.

  • При реализации шаблона get / set промежуточная переменная используется в качестве контейнера, в который может быть помещено значение и извлечено значение. Промежуточная переменная обычно начинается с подчеркивания. эта промежуточная переменная является закрытой, чтобы обеспечить доступ к ней только через вызовы get / set. Посмотрите ответ Брэндона, поскольку его ответ демонстрирует наиболее часто используемые синтаксические соглашения для реализации get / set.


5

Это означает, что если вы создадите переменную типа Genre, вы сможете получить доступ к переменной как свойству

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

Get set - это модификаторы доступа к свойству. Get читает поле свойства. Set устанавливает значение свойства. Получить как доступ только для чтения. Установить как доступ только для записи. Чтобы использовать свойство как чтение и запись, необходимо использовать как get, так и set.


1
я думаю, что наборы не являются модификаторами доступа, на самом деле они являются аксессорами. Модификаторы доступа: публичные, частные, внутренние и т. Д.
Rohit Arora

1

Get вызывается, когда свойство появляется справа (RHS). Set вызывается, когда свойство отображается слева (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 и загружаю данные из константы в класс Selected List.

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.