Может ли кто-нибудь дать очень простое объяснение автоматических свойств в С#, их назначение и, возможно, несколько примеров? Пожалуйста, постарайтесь говорить по-человечески!
Что такое автоматические свойства в C# и какова их цель?
Ответы (11)
Автоматические свойства используются, когда в средствах доступа к свойствам не требуется дополнительная логика.
Объявление будет выглядеть примерно так:
public int SomeProperty { get; set; }
Это просто синтаксический сахар, поэтому вам не нужно писать следующий более длинный код:
private int _someField;
public int SomeProperty
{
get { return _someField;}
set { _someField = value;}
}
public int SomeProperty;
Разве это не то же самое? Я имею в виду, если здесь вообще нет приватной переменной, то зачем нам вообще нужны Свойства?
- person user2048204; 07.11.2016
Редактировать: немного расширяясь, они используются, чтобы упростить использование закрытых переменных в классе, но сделать их видимыми за пределами класса (без возможности их изменения).
Да, и еще одно преимущество автоматических свойств заключается в том, что вы можете использовать их в интерфейсах! (которые не допускают переменных-членов любого типа)
С обычными свойствами вы можете сделать что-то вроде:
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 также предупредил меня:
- http://msdn.microsoft.com/en-us/library/bb384054.aspx
- http://weblogs.asp.net/dwahlin/archive/2007/12/04/c-3-0-features-automatic-properties.aspx
setExample
был private
или вообще не было сеттера.
- person Moira; 02.08.2017
Если вы спрашиваете, почему вы должны использовать свойства или автоматические свойства, это философия дизайна, стоящая за этим.
Один из важных принципов дизайна заключается в том, что вы никогда не раскрываете поля как общедоступные, а всегда получаете доступ ко всему через свойства. Это связано с тем, что вы никогда не можете сказать, когда к полю обращаются и, что более важно, когда оно установлено. Теперь в большинстве случаев не требуется никакой обработки при установке или получении значения (например, проверка диапазона). Вот почему были созданы автоматические свойства. Это простой однострочный способ создания свойства. Резервное хранилище для него создается компилятором.
Хотя это то, что я делаю даже для своих внутренних программ, это, вероятно, более важно для тех, которые предназначены для публичного использования (для продажи, с открытым исходным кодом и т. д.). Если вы используете автоматическое свойство, а позже решите, что вам нужно сделать что-то еще в 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)
Это просто ярлык кода, позволяющий программисту сэкономить несколько нажатий клавиш. Вместо того, чтобы печатать все это:
private string _lastName;
public string LastName {
get {
return _lastName;
}
set {
_lastName = value;
}
}
вы можете просто ввести:
public string LastName {
get; set;
}
и пусть компилятор сгенерирует остальные автоматически.
Многие люди уже заявили, что автоматические свойства — это синтаксический сахар — сокращенный способ записи простых свойств. Я расскажу о различиях между общедоступной переменной и общедоступным свойством и о том, почему при переключении между ними вам потребуется перекомпилировать. Возьмите следующее:
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», но это может быть что-то еще, что очень похоже. Пока есть понимание, это, вероятно, не имеет большого значения. В конце концов, они все равно становятся адресами памяти :-)
Из Автоматически реализуемые свойства (Руководство по программированию на C#):
В C# 3.0 и более поздних версиях автоматически реализуемые свойства делают объявление свойств более кратким, когда в средствах доступа к свойствам не требуется дополнительная логика. Они также позволяют клиентскому коду создавать объекты.
Когда вы объявляете свойство, компилятор создает частное анонимное вспомогательное поле, доступ к которому можно получить только через методы доступа get и set свойства.
class Person
{
public string Name { get; set; }
}
Упрощая принятый ответ, вы можете также использовать:
public int SomeProperty { get; private set; }
Это имеет тот же эффект, и вам больше не нужно создавать для этого другую переменную.
public int SomeProperty { get; }
(без private set
) в своем конструкторе, как если бы ваше неявное вспомогательное поле было помечено readonly
.
- person ruffin; 18.09.2018
В более ранних версиях C#, чтобы использовать свойства, вам нужно было создать поле для хранения значения (называемое резервным хранилищем):
private string _something;
public string Prop { get { return _something; } }
Начиная с C# 3.0, это требование больше не требуется, и компилятор автоматически создаст для вас резервное хранилище, поэтому нет необходимости объявлять поле _something.
Подробнее об этом можно прочитать здесь: http://msdn.microsoft.com/en-us/library/bb384054.aspx
Надеюсь это поможет.
Помимо аспектов, упомянутых в предыдущем ответе, я бы также заметил некоторые различия между автоматическими свойствами и полями, поскольку они выглядят очень похожими и их использование практически одинаково:
- может быть легко преобразован в «классические» свойства, когда это необходимо, без нарушения каких-либо контрактов с вызывающими свойствами
- разрешать точки останова на get/set при разработке в Visual Studio. Это особенно полезно, когда изменения вносятся путем отражения, а источник изменений не очевиден.
Для любых читателей 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"
Лично мне такой подход нравится больше, поскольку вы можете ясно видеть в своем потребляющем коде, когда работаете с внутренними полями или, возможно, открытыми свойствами.
Используйте приведенный ниже код:
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);
}
}