Примечание: это было опубликовано, когда я только начинал изучать C#. Обладая знаниями 2014 года, я действительно могу сказать, что автоматические свойства - это одно из лучших вещей, которые когда-либо происходили с языком C#.
Я привык создавать свои свойства на C#, используя частное и общедоступное поля:
private string title;
public string Title
{
get { return title; }
set { title = value; }
}
Теперь, с .СЕТЬ 3.0, мы получили автоматические свойства:
public string Title { get; set; }
Я знаю, что это скорее философские / субъективные вопросы, но есть ли причина использовать эти автоматические свойства, кроме сохранения пяти строк кода для каждого поля? Мое личное недовольство заключается в том, что эти свойства скрывают от меня вещи, и я не большой поклонник черной магии.
Фактически, скрытое частное поле даже не отображается в отладчике, что нормально, учитывая тот факт, что функции get / set ничего не делают. Но когда я действительно хочу реализовать некоторую логику геттера / сеттера, мне все равно приходится использовать частную / общедоступную пару.
Я вижу преимущество в том, что я экономлю много кода (одна против шести строк), не теряя возможности позже изменять логику получения / установки, но опять же, я уже могу это сделать, просто объявив общедоступное поле «Заголовок открытой строки» без потребность {получить; набор; } блок, таким образом даже сэкономив больше кода.
Итак, что мне здесь не хватает? Зачем кому-то на самом деле нужно использовать автоматические свойства?





Я лично люблю авто свойства. Что не так с сохранением строк кода? Если вы хотите сделать что-то в геттерах или сеттерах, не проблема преобразовать их в нормальные свойства позже.
Как вы сказали, вы можете использовать поля, и если вы хотите добавить к ним логику позже, вы должны преобразовать их в свойства. Но это может вызвать проблемы с любым использованием отражения (и, возможно, где-нибудь еще?).
Также свойства позволяют вам устанавливать разные уровни доступа для геттера и сеттера, чего вы не можете сделать с полем.
Я думаю, это то же самое, что и ключевое слово var. Дело личных предпочтений.
Три больших недостатка использования полей вместо свойств:
«Если вы начинаете использовать поле, вы не сможете позже (легко) изменить его на свойство», извините, но почему?
@Homam В основном любой потребительский код, который использует отражение в ваших полях, сломается, поскольку им придется переключиться с использования FieldInfo на PropertyInfo.
@Homam Кроме того, изменение поля на свойство нарушает двоичную совместимость, требуя от всех потребителей поля перекомпиляции.
Помимо проблем с перекомпиляцией и отражением, очень легко инкапсулировать поля с помощью Visual Studio: Ctrl-R + E позволит вам превратить поле в свойство с соответствующими геттерами / сеттерами. (или щелкните поле правой кнопкой мыши, измените коэффициент, инкапсулируйте поле).
Поля @Hommam - это l-значения (они переменные), а свойства - нет. То, что могло быть скомпилировано, когда это было поле, может не быть, когда это свойство.
Мы постоянно используем их в Stack Overflow.
Вам также может быть интересно обсуждение Свойства против общедоступных переменных. ИМХО, это действительно то, на что это реакция, и для этой цели это здорово.
Я постоянно использую автоматические свойства. До C# 3 я не мог утруждать себя набором текста и вместо этого просто использовал общедоступные переменные.
Единственное, чего мне не хватает, так это возможности сделать это:
public string Name = "DefaultName";
Вы должны перенести значения по умолчанию в свои конструкторы со свойствами. скучный :-(
С помощью инициализаторов автоматических свойств из C# 6 вы скоро сможете это сделать: public string Name { get; set; } = "DefaultName";blogs.msdn.com/b/csharpfaq/archive/2014/11/20/…
Я думаю, что любая конструкция, которая интуитивно понятна и сокращает количество строк кода, является большим плюсом.
Именно такие функции делают такие мощные языки, как Ruby (это и динамические функции, которые также помогают уменьшить лишний код).
У Ruby это всегда было:
attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter
Единственная проблема, с которой я сталкиваюсь, это то, что они не заходят достаточно далеко. В том же выпуске компилятора, в котором добавлены автоматические свойства, добавлены частичные методы. Почему они не соединили их вместе, мне непонятно. Простой "частичный On
Вы можете поместить несколько частичных методов в другой метод. Создание какого-либо автоматического шаблона для них могло бы сбить с толку.
Да, он сохраняет код только. Когда их много, читать легче. Их быстрее писать и легче поддерживать. Сохранение кода - всегда хорошая цель.
Вы можете установить разные области:
public string PropertyName { get; private set; }
Так что свойство можно изменить только внутри класса. На самом деле это не является неизменным, поскольку вы все еще можете получить доступ к частному сеттеру через отражение.
Начиная с C# 6, вы также можете создавать истинные свойства readonly, то есть неизменяемые свойства, которые нельзя изменить вне конструктора:
public string PropertyName { get; }
public MyClass() { this.PropertyName = "whatever"; }
Во время компиляции это станет:
readonly string pName;
public string PropertyName { get { return this.pName; } }
public MyClass() { this.pName = "whatever"; }
В неизменяемых классах с большим количеством членов это позволяет сэкономить много лишнего кода.
«Таким образом, вы не потеряете никакой функциональности». как вы их отлаживаете?
@wal - что там отлаживать? С этой точки зрения вы в основном имеете дело с переменными-членами.
В исходном примере плакатов, как узнать, когда myObj.Title меняется с одного значения на другое?
@wal - Вы можете поставить на них точку останова, точно так же, как вы можете получить доступ к переменной-члену, вы просто не можете войти в них. Но зачем вам это нужно? То, что на самом деле делают автоматические свойства, тривиально и автоматически генерируется, если у вас есть ошибки, в одном месте, где они вряд ли будут.
нам может понадобиться взять это за пределы Кита. :)
Но хорошо, предположим, что у вас есть много вызовов метода установки myObj.Title ... вы хотите увидеть, где значение изменяется с "text" на null, то есть условную точку останова. как ты это добился? вы даже не можете установить точку останова на сеттере
Просто интересно про "частный набор", доступный только для чтения, классное спасибо.
Здесь следует отметить, что, насколько я понимаю, это синтаксический сахар только на конце C# 3.0, что означает, что IL, сгенерированный компилятором, такой же. Я согласен с тем, чтобы избегать черной магии, но все же меньшее количество строк для одного и того же обычно хорошо.
На мой взгляд, вы всегда должны использовать автоматические свойства вместо общедоступных полей. Тем не менее, вот компромисс:
Начните с поля внутренний, используя соглашение об именах, которое вы использовали бы для свойства. Когда вы впервые либо
Сделай это:
Ваш клиентский код менять не нужно.
Однако когда-нибудь ваша система вырастет, и вы разложите ее на отдельные сборки и несколько решений. Когда это произойдет, любые открытые поля снова будут преследовать вас, потому что, как сказал Джефф, изменение общедоступного поля на общедоступное свойство - критическое изменение API.
Авто-свойства - такая же черная магия, как и все остальное в C#. Если вы подумаете об этом с точки зрения компиляции до IL, а не о его расширении до обычного свойства C#, это будет намного меньше черной магии, чем множество других языковых конструкций.
Я использую CodeRush, он быстрее авто-свойств.
Сделать это:
private string title;
public string Title
{
get { return title; }
set { title = value; }
}
Всего требуется восемь нажатий клавиш.
Если я зажму CTRL и V, я могу вставить много-много всего / очень быстро /, но это не делает его «лучше». Как это отвечает на исходный вопрос?
Что ж, с фрагментами кода одноименное автоматическое свойство будет состоять всего из семи нажатий клавиш;)
Одна вещь, о которой, кажется, никто не упомянул, - это то, что автоматические свойства, к сожалению, не полезны для неизменяемых объектов (обычно неизменяемых структур). Потому что для этого вам действительно нужно:
private readonly string title;
public string Title
{
get { return this.title; }
}
(где поле инициализируется в конструкторе с помощью переданного параметра, а затем доступно только для чтения.)
Таким образом, это имеет преимущества перед простым автосвойством get / private set.
Если у вас есть структура, изменение какого-либо свойства в ней приводит к новой структуре. Это было бы проблемой только в том случае, если бы вам нужен был внутренне неизменяемый ссылочный тип - я не вижу причины, по которой он вам когда-либо понадобится.
@Keith: Ваше первое предложение кажется фактически неверным.
@Domenic: Я думаю, он ограничивает свое определение структур неизменяемыми.
Разве public string Title { get; private set; } не приведет к тому же результату? Конечно, вы могли бы изменить его изнутри класса, но если вы это сделаете, у вас будут другие проблемы ...: p
Идея - защитное кодирование.
@Svish, это не совсем то же самое, потому что поле только для чтения может быть установлено только при построении или объявлении, где как частный сеттер может быть установлен и для неконструкторских методов в том же классе.
@ zooone9243, Да, и, как я уже сказал, если мы не можем удержаться от установки значения внутри класса, которое должно быть неизменным, тогда у нас будут другие проблемы.
@Svish: проблемы типа работы в команде, состоящей из программистов разного уровня подготовки?
@Svish - с помощью этого аргумента ключевое слово readonly в C# никогда не должно использоваться, потому что его использование будет означать, что мы скрываем эти «разные проблемы»
@Domenic: Нет, проблемы вроде работы в команде, где разработчики делают то, чего делать не должны. Типа: «Эй, я знаю, что это должен быть неизменяемый объект, но давайте просто изменим эту переменную, чтобы заставить ее работать» - вроде того ...
Я просто хочу сказать, что с точки зрения внешнего API это не будет иметь большого значения. Итак, при желании можно использовать автоматические свойства. Лучше всего, конечно, было бы, если бы вы могли сделать что-то вроде public string Title { get; private readonly set; }
Иногда я разделяю типы .NET на две группы: типы, которые могут быть написаны на .NET (HttpRequest, Button), и те, которые могут быть написаны только под .NET и имеют «интерфейс» .NET, чтобы мы могли их использовать (object, Можно подумать, что Thread относится к более позднему типу. Что ж, это не так. Любой может переписать его на C#. Становится ясно, что поля только для чтения ДОЛЖНЫ быть обновляемыми в любой момент времени, потому что десериализация графа в противном случае потребовала бы магии, поскольку в общем случае нет определенной связи между параметрами ctor и полями только для чтения : BinaryFormatter
@Domenic: Я не понимаю ... разве вы не можете сделать это с помощью авто-свойств ?:
public string Title { get; }
или же
public string Title { get; private set; }
Это то, о чем вы говорите?
Вы можете (последнее; первое не будет компилироваться), но тогда поле не будет неизменным внутри вашего объекта.
Предупреждение, только структуры являются неизменяемыми, если они отмечены только для чтения, классы просто не назначаются.
Это просто, это коротко, и если вы хотите создать реальную реализацию внутри тела свойства где-нибудь в конце строки, это не нарушит внешний интерфейс вашего типа.
Так просто.
От Бьярна Страуструпа, создателя C++:
I particularly dislike classes with a lot of get and set functions. That is often an indication that it shouldn't have been a class in the first place. It's just a data structure. And if it really is a data structure, make it a data structure.
И знаешь, что? Он прав. Как часто вы просто обертываете частные поля в get и set, фактически ничего не делая внутри get / set, просто потому, что это «объектно-ориентированное» действие. Это решение проблемы Microsoft; это в основном общедоступные поля, к которым вы можете привязаться.
Я действительно думаю, что здесь должно быть больше очков. Слишком много людей рассматривают свойства auto как зеленый свет для написания ужасно инкапсулированных (или вообще не инкапсулированных) классов, которые являются не более чем прославленным публичным полем. Конечно, это больше проблема с тем, как люди используют инструмент, а не с самим инструментом, но я думаю, что это важно упомянуть при обсуждении свойств в целом.
Моя самая большая проблема с автоматическими свойствами заключается в том, что они предназначены для экономии времени, но я часто обнаруживаю, что позже мне приходится расширять их до полноценных свойств.
В VS2008 отсутствует рефакторинг Расчленить авто-свойство.
Тот факт, что у нас есть рефакторинг инкапсулировать поле, позволяет мне быстрее использовать только общедоступные поля.
Я всегда создаю свойства вместо общедоступных полей, потому что вы можете использовать свойства в определении интерфейса, вы не можете использовать общедоступные поля в определении интерфейса.
«Мое личное недовольство заключается в том, что эти свойства скрывают от меня вещи, и я не большой поклонник черной магии». Хм? Вы ЗНАЕТЕ, что компилятор все время скрывает от вас тонну, верно? Если вы не пишете ассемблер (или, точнее, действительные 1 и 0 для вашего кода), ВСЕ, что вы пишете, скрывает от вас информацию.