Что такое автоматические свойства в C# и какова их цель?

Может ли кто-нибудь дать очень простое объяснение автоматических свойств в С#, их назначение и, возможно, несколько примеров? Пожалуйста, постарайтесь говорить по-человечески!


person dennis    schedule 14.05.2011    source источник


Ответы (11)


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

public int SomeProperty { get; set; }

Это просто синтаксический сахар, поэтому вам не нужно писать следующий более длинный код:

 private int _someField;
 public int SomeProperty 
 {
    get { return _someField;}
    set { _someField = value;}
 }
person Stecya    schedule 14.05.2011
comment
@Cody Grey @Stecya Почему я не могу просто использовать public int SomeProperty; Разве это не то же самое? Я имею в виду, если здесь вообще нет приватной переменной, то зачем нам вообще нужны Свойства? - person user2048204; 07.11.2016
comment
@ user2048204, потому что свойство отличается от переменной blog.codinghorror.com/properties-vs-public -переменные - person Slai; 18.11.2016
comment
@user2048204 user2048204 Есть частная переменная; Это автоматически сгенерированное анонимное частное поле. Но вы пишете свой код для доступа к нему из класса через имя общедоступного свойства (что было бы функционально идентично доступу к нему напрямую, в этом случае, когда в методе доступа не было дополнительной логики). - person Sepster; 16.01.2018
comment
когда вы исследуете автоматически реализуемое свойство с помощью инструмента ildasm, вы узнаете, что за каждым автоматически реализованным свойством стоят следующие автоматически созданные поля: частный элемент данных и два метода, которые работают как геттер и сеттер для этого частного поля. - person Ammar; 28.07.2018
comment
В ответе Stecya/AustinWBryan чего-то не хватает. если автосвойство создает частное поле за кулисами, почему интерфейс может определять автосвойство, но не поля? Не может быть, чтобы автосвойства были просто синтаксическим сахаром, потому что это было бы ошибкой компилятора, когда я использую их в интерфейсах. - person Gregory Fenn; 28.01.2019
comment
@GregoryFenn Нет, если поля автоматически генерируются для класса, реализующего интерфейс, а не для интерфейса. - person leoap; 05.03.2020

Редактировать: немного расширяясь, они используются, чтобы упростить использование закрытых переменных в классе, но сделать их видимыми за пределами класса (без возможности их изменения).

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

С обычными свойствами вы можете сделать что-то вроде:

private string example;
public string Example 
{
    get { return example; }
    set { example = value; }
}

Автоматические свойства позволяют создать что-то действительно лаконичное:

public string Example { get; set; }

Итак, если вы хотите создать поле, в котором его можно установить только внутри класса, вы можете сделать:

public string Example { get; private set; }

Это будет эквивалентно:

private string example;
public string Example 
{
    get { return example; }
    private set { example = value; }
}

Или в Java:

private String example;

public String getExample() {
    return example;
}

private void setExample(String value) {
    example = value;
}

Изменить: @Paya также предупредил меня:

person Darkzaelus    schedule 14.05.2011
comment
Я бы также добавил эти две ссылки: MSDN и Блог ASP.NET . - person Paya; 14.05.2011
comment
Для эквивалента в Java потребуется, чтобы setExample был private или вообще не было сеттера. - person Moira; 02.08.2017
comment
Это должен быть выбранный ответ, так как текущий не дает реальной причины использовать пустой get/get вместо простого поля (сказано резко, он просто указывает, что существует простой способ объявить бесполезные методы). - person mins; 26.03.2019

Если вы спрашиваете, почему вы должны использовать свойства или автоматические свойства, это философия дизайна, стоящая за этим.

Один из важных принципов дизайна заключается в том, что вы никогда не раскрываете поля как общедоступные, а всегда получаете доступ ко всему через свойства. Это связано с тем, что вы никогда не можете сказать, когда к полю обращаются и, что более важно, когда оно установлено. Теперь в большинстве случаев не требуется никакой обработки при установке или получении значения (например, проверка диапазона). Вот почему были созданы автоматические свойства. Это простой однострочный способ создания свойства. Резервное хранилище для него создается компилятором.

Хотя это то, что я делаю даже для своих внутренних программ, это, вероятно, более важно для тех, которые предназначены для публичного использования (для продажи, с открытым исходным кодом и т. д.). Если вы используете автоматическое свойство, а позже решите, что вам нужно сделать что-то еще в set или get, вы можете легко изменить свой код, не нарушая общедоступный интерфейс.

Обновить

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

В качестве теста я создал проект библиотеки и объявил свойство с именем TestData. Я создал совершенно новый проект только для того, чтобы использовать эту библиотеку. Все работало, как и ожидалось. Затем я изменил свойство на общедоступное поле (имя осталось прежним) и скопировал новую библиотеку DLL без перекомпиляции потребляющего проекта. В результате возникло исключение, так как код ожидал найти методы свойств методов get_TestData и set_TestData, но доступ к полям через методы не осуществляется.

Unhandled Exception: System.MissingMethodException: Method not found: 'Void TestLibrary.TesterClass.set_TestData(System.String)'.
   at TestLibraryConsumer.Program.Main(String[] args)
person Jim    schedule 14.05.2011
comment
Если вы используете автоматическое свойство, а позже решите, что вам нужно сделать что-то еще в наборе или получить, вы можете легко изменить свой код, не нарушая общедоступный интерфейс. одинаково легко заменить поле свойством с тем же именем, если вам позже потребуется некоторая обработка перед присвоением значения или чтением. Но пока вам не понадобится эта обработка, нет видимых преимуществ в объявлении свойства по сравнению с объявлением поля. Таким образом, OP по-прежнему действителен (этот ответ описывает фактическое преимущество наличия пустых методов get/set). - person mins; 26.03.2019
comment
@мин. Если код полностью ваш, вы правы. Я обновил свой ответ, чтобы уточнить, почему переключение между свойствами и полями все еще может пойти не так. - person Jim; 26.03.2019

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

private string _lastName;
public string LastName {
    get {
        return _lastName;
    }
    set {
        _lastName = value;
    }
}  

вы можете просто ввести:

public string LastName {
    get; set;
} 

и пусть компилятор сгенерирует остальные автоматически.

person Richard Brightwell    schedule 14.05.2011
comment
Компилятор также создает частное анонимное резервное поле, доступ к которому можно получить только с помощью методов доступа get и set свойства. - person Chris Fulstow; 14.05.2011

Многие люди уже заявили, что автоматические свойства — это синтаксический сахар — сокращенный способ записи простых свойств. Я расскажу о различиях между общедоступной переменной и общедоступным свойством и о том, почему при переключении между ними вам потребуется перекомпилировать. Возьмите следующее:

public class MyClass
{
    public int MyPublicVariable = 0;

    public int MyPublicProperty
    {
        get;
        set;
    }
}

После компиляции, концептуально, он на самом деле выглядит примерно так:

public class MyClass
{
    public int MyPublicVariable = 0;

    private int MyPublicProperty = 0;

    public int get_MyPublicProperty()
    {
        return MyPublicProperty;
    }

    public void set_MyPublicProperty( int value )
    {
        MyPublicProperty = value;
    }
}

Давным-давно свойства были изобретены как быстрый и простой способ определения пар методов get и set. Это сделало код более читабельным и понятным, поскольку он передал намерение и обеспечил согласованность.

MyClass myClass = new MyClass();

myClass.MyPublicVariable = 2;

myClass.MyPublicProperty = 2;

После компиляции, опять же концептуально, он выглядит примерно так:

MyClass myClass = new MyClass();

myClass.MyPublicVariable = 2;

myClass.set_MyPublicProperty( 2 );

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

Также были комментарии по поводу интерфейсов. Интерфейсы — это, по сути, контракт, гарантирующий наличие определенных методов в любом реализующем их классе. Как мы знаем из вышеизложенного, свойства представляют один или два метода, поэтому они отлично работают в интерфейсах.

Надеюсь, это немного поможет.

Вот еще один пример, который может быть интересен:

public class MyClass
{
    private int[] _myArray = new int[ 5 ];

    public int MyArray[ int index ]
    {
        get
        {
            return _myArray[ index ];
        }
        set
        {
            _myArray[ index ] = value;
        }
     }
}
public class MyClass
{
    private int[] _myArray = new int[ 5 ];

    public int get_MyArray( int index )
    {
        return _myArray[ index ];
    }

    public void set_MyArray( int index, int value )
    {
        _myArray[ index ] = value;
    }
}

Обратите внимание: я не могу точно вспомнить сигнатуры методов, используемые при декомпиляции свойств. Я думаю, что это «get_XXX» и «set_XXX», но это может быть что-то еще, что очень похоже. Пока есть понимание, это, вероятно, не имеет большого значения. В конце концов, они все равно становятся адресами памяти :-)

person Chris    schedule 29.08.2019

Из Автоматически реализуемые свойства (Руководство по программированию на C#):

В C# 3.0 и более поздних версиях автоматически реализуемые свойства делают объявление свойств более кратким, когда в средствах доступа к свойствам не требуется дополнительная логика. Они также позволяют клиентскому коду создавать объекты.
Когда вы объявляете свойство, компилятор создает частное анонимное вспомогательное поле, доступ к которому можно получить только через методы доступа get и set свойства.

class Person
{
       public string Name { get; set; }
}
person Akram Shahda    schedule 14.05.2011

Упрощая принятый ответ, вы можете также использовать:

public int SomeProperty { get; private set; }

Это имеет тот же эффект, и вам больше не нужно создавать для этого другую переменную.

person Marek S.    schedule 07.09.2018
comment
Интересно, что вы все еще можете установить значение для public int SomeProperty { get; } (без private set) в своем конструкторе, как если бы ваше неявное вспомогательное поле было помечено readonly. - person ruffin; 18.09.2018
comment
Это предложение работает в случае, когда вы хотите иметь свойство, которое вам нужно получить только другими классами и иметь возможность обновлять его другими методами в этом классе. - person DragonSpit; 21.02.2019

В более ранних версиях C#, чтобы использовать свойства, вам нужно было создать поле для хранения значения (называемое резервным хранилищем):

private string _something;
public string Prop { get { return _something; } }

Начиная с C# 3.0, это требование больше не требуется, и компилятор автоматически создаст для вас резервное хранилище, поэтому нет необходимости объявлять поле _something.

Подробнее об этом можно прочитать здесь: http://msdn.microsoft.com/en-us/library/bb384054.aspx

Надеюсь это поможет.

person lysergic-acid    schedule 14.05.2011
comment
Это С# 3.0 и более поздние версии. Документация, на которую вы ссылаетесь, говорит об этом вверху. - person Cody Gray; 14.05.2011

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

  • может быть легко преобразован в «классические» свойства, когда это необходимо, без нарушения каких-либо контрактов с вызывающими свойствами
  • разрешать точки останова на get/set при разработке в Visual Studio. Это особенно полезно, когда изменения вносятся путем отражения, а источник изменений не очевиден.
person Alexei - check Codidact    schedule 21.01.2020

Для любых читателей VB.NET это реализовано несколько иначе. Например:

''' <summary>The property is declared and can be initialized.</summary>
Public Property MyProperty As String = "SomeValue"

Однако связанное поле доступно явно, если добавить префикс подчеркивания:

Dim sConcat As String = _MyProperty + _MyProperty
_MyProperty = sConcat

И во внешнем коде:

Dim sMyValue As String = oMyClassObj.MyProperty ' = "SomeValueSomeValue"

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

person SteveCinq    schedule 02.01.2019

Используйте приведенный ниже код:

using System;

class My Class
{
    public string Dummy { get; set; }

    public My Class()
    {
        Dummy = "I'm dummy property";
    }
}

class Program 
{
    static void Main() 
    {
            var my Class = new My Class();
             Console .Write Line (my Class .Dummy);
    }
}
person chaudhray nawaz    schedule 28.05.2019
comment
Я не уверен, что этот ответ что-то добавляет, поскольку он не дает очень простого объяснения автоматических свойств в C#, их назначения и, возможно, некоторых примеров, он также не компилируется. - person Rob; 30.05.2019