Другие языки программирования и технологии

C# get и set

Объясните пожалуйста назначение этих свойств вот в таком виде:
public string myString { get; set; }

если я правильно понимаю то при компилировании это разворачивается в

private string _myString;
public string myString
{
get { return _myString; }
set { _myString = value; }
}

но какой в этом смысл? Вызов из main выглядит одинаково, что с get set, что без них.
myClass s = new myClass();
s.myString = "123";
Console.WriteLine(s.myString);

Я могу понять смысл get и set как отдельных функций. Но я постоянно наблюдаю что их пишут просто {get; set;} и все.
Одним из соглашений объектно-ориентированного программирования и разработки является инкапсуляция данных. Инкапсуляция данных означает, что поля типа НИ В КОЕМ СЛУЧАЕ не следует открывать для общего доступа, так как в этом случае слишком просто написать код, способный испортить сведения о состоянии объекта путем ненадлежащего применения полей. Банальный пример, поле возраста: people.age = -5 рушит всю логику. Особенно если вы работаете в команде или забыли за что это поле отвечает и задали неправильное значение. То есть соглашения устраняют потенциальные ошибки, которые вы можете совершить по неосторожности.

Есть и другие причины для инкапсуляции доступа к полям данных типа. Допустим, вам нужен доступ к полю, чтобы что-то сделать, разместить в кэше некоторое значение или создать какой-то внутренний объект, создание которого было отложено, причем обращение к полю не должно нарушать безопасность потоков. Или, скажем, поле является логическим и его значение представлено не байтами в памяти, а вычисляется по некоторому алгоритму.

Каждая из этих причин заставляет при разработке типов, во-первых, помечать абсолютно все поля как закрытые (private), во-вторых, давать пользователю вашего типа возможность получения и задания сведений о состоянии через специальные методы, предназначенные исключительно для этого. Методы, выполняющие функции оболочки для доступа к полю, обычно называют аксессорами (accessor). Аксессоры могут выполнять дополнительную зачистку, гарантируя, что сведения о состоянии объекта никогда не будут искажены.

private string _myString;
public string getMyString()
{
return _myString;
}
public void setMyString(string value)
{
_myString = value
}

Как видите, у инкапсуляции данных есть два недостатка: во-первых, из-за реализации дополнительных методов приходится писать более длинный код, во-вторых, вместо простой ссылки на имя поля пользователям типа приходится вызывать соответствующие методы. Но благодаря свойствам, этого можно избежать.

Поэтому код:

public string myString { get; set; }

Является заменой вот такого кода:
private string _myString;
public string myString
{
{ return _myString; }
{ _myString = value; }
}

Который на самом деле должен выглядеть как-то так без свойств:
private string _myString;
public string getMyString()
{
return _myString;
}
public void setMyString(string value)
{
_myString = value
}

И все потому, что бы не делать потенциальных ошибок и следовать ООП парадигме и ее правилам. Даже если вы считаете, что данные никак нельзя испортить, лучше иметь привычку делать все правильно. И согласитесь, писать одну строчку кода свойств взамен аксессоров в пять строк и их вывод, это очень разные вещи.

Ну и да, закрытое свойство при использовании свойств генерируется автоматически и его не обязательно объявлять.
Олег Авсеенко
Олег Авсеенко
40 015
Лучший ответ
Igor Kazakov Вот только свойства используются гораздо шире, чем вы сейчас описали. И если раньше они преследовали инкапсуляцию, как цель, то теперь они используются и для вспомогательных нужд. Допустим, для предварительной обработки данных во время get или set. Причем это использует и сам Майкрософт. Пример: реализация интерфейса INotifyPropertyChanged, который предполагает вызов эвента при изменении свойства. Этот вызов осуществляется в set после назначения нового значения полю.

Что касается автопроперти, то это исключительно синтаксический сахарю
Теоретически, в таком "пустом" свойстве никакого смысла.
Практически - кое-какие библиотеки (например, использующие рефлексию - типа сериализаторов, или какие-нибудь привязки данных к GUI) могут работать только со свойствами или, наоборот, только с полями. Приходится извращаться.
ФР
Фима Рудой
15 749
например можно сделать так
public string myString
{
get { return _myString + "some text"; }
set { _myString = value; }
}
Даурен Даурен
Даурен Даурен
7 018
Синтаксический сахар. Просто для сокращения количества кода.

Кста, хз как до них, но в интерфейсах так же можно указывать проперти.

public interface ITestInterface
{
string MyString { get; }
}

При имплементации в классе будет

public string MyString { get; private set; }