Автоматические свойства C# 3.0 - полезно или нет?

Примечание: это было опубликовано, когда я только начинал изучать 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 ничего не делают. Но когда я действительно хочу реализовать некоторую логику геттера / сеттера, мне все равно приходится использовать частную / общедоступную пару.

Я вижу преимущество в том, что я экономлю много кода (одна против шести строк), не теряя возможности позже изменять логику получения / установки, но опять же, я уже могу это сделать, просто объявив общедоступное поле «Заголовок открытой строки» без потребность {получить; набор; } блок, таким образом даже сэкономив больше кода.

Итак, что мне здесь не хватает? Зачем кому-то на самом деле нужно использовать автоматические свойства?

«Мое личное недовольство заключается в том, что эти свойства скрывают от меня вещи, и я не большой поклонник черной магии». Хм? Вы ЗНАЕТЕ, что компилятор все время скрывает от вас тонну, верно? Если вы не пишете ассемблер (или, точнее, действительные 1 и 0 для вашего кода), ВСЕ, что вы пишете, скрывает от вас информацию.

Charles Boyung 10.06.2010 19:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
155
1
47 275
18
Перейти к ответу Данный вопрос помечен как решенный

Ответы 18

Я лично люблю авто свойства. Что не так с сохранением строк кода? Если вы хотите сделать что-то в геттерах или сеттерах, не проблема преобразовать их в нормальные свойства позже.

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

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

Я думаю, это то же самое, что и ключевое слово var. Дело личных предпочтений.

Три больших недостатка использования полей вместо свойств:

  1. Вы не можете привязать данные к полю, тогда как можете - к свойству
  2. Если вы начинаете использовать поле, вы не сможете позже (легко) изменить их на свойство
  3. Есть некоторые атрибуты, которые вы можете добавить к свойству, но не можете добавить в поле.

«Если вы начинаете использовать поле, вы не сможете позже (легко) изменить его на свойство», извините, но почему?

Homam 11.10.2010 17:26

@Homam В основном любой потребительский код, который использует отражение в ваших полях, сломается, поскольку им придется переключиться с использования FieldInfo на PropertyInfo.

WCWedin 21.10.2010 20:10

@Homam Кроме того, изменение поля на свойство нарушает двоичную совместимость, требуя от всех потребителей поля перекомпиляции.

Odrade 20.01.2011 21:20

Помимо проблем с перекомпиляцией и отражением, очень легко инкапсулировать поля с помощью Visual Studio: Ctrl-R + E позволит вам превратить поле в свойство с соответствующими геттерами / сеттерами. (или щелкните поле правой кнопкой мыши, измените коэффициент, инкапсулируйте поле).

JoeBrockhaus 07.11.2012 22:30

Поля @Hommam - это l-значения (они переменные), а свойства - нет. То, что могло быть скомпилировано, когда это было поле, может не быть, когда это свойство.

Mark 27.05.2015 00:07
Ответ принят как подходящий

Мы постоянно используем их в 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/…

Carlos Muñoz 26.03.2015 20:01

Я думаю, что любая конструкция, которая интуитивно понятна и сокращает количество строк кода, является большим плюсом.

Именно такие функции делают такие мощные языки, как Ruby (это и динамические функции, которые также помогают уменьшить лишний код).

У Ruby это всегда было:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

Единственная проблема, с которой я сталкиваюсь, это то, что они не заходят достаточно далеко. В том же выпуске компилятора, в котором добавлены автоматические свойства, добавлены частичные методы. Почему они не соединили их вместе, мне непонятно. Простой "частичный OnИзмененный "сделал бы эти вещи действительно действительно полезными."

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

Matthew Whited 12.09.2010 16:23

Да, он сохраняет код только. Когда их много, читать легче. Их быстрее писать и легче поддерживать. Сохранение кода - всегда хорошая цель.

Вы можете установить разные области:

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 25.10.2010 07:43

@wal - что там отлаживать? С этой точки зрения вы в основном имеете дело с переменными-членами.

Keith 26.10.2010 15:17

В исходном примере плакатов, как узнать, когда myObj.Title меняется с одного значения на другое?

wal 27.10.2010 04:45

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

Keith 27.10.2010 18:45

нам может понадобиться взять это за пределы Кита. :)

wal 28.10.2010 17:10

Но хорошо, предположим, что у вас есть много вызовов метода установки myObj.Title ... вы хотите увидеть, где значение изменяется с "text" на null, то есть условную точку останова. как ты это добился? вы даже не можете установить точку останова на сеттере

wal 28.10.2010 17:12

Просто интересно про "частный набор", доступный только для чтения, классное спасибо.

CallMeLaNN 01.02.2011 05:11

Здесь следует отметить, что, насколько я понимаю, это синтаксический сахар только на конце C# 3.0, что означает, что IL, сгенерированный компилятором, такой же. Я согласен с тем, чтобы избегать черной магии, но все же меньшее количество строк для одного и того же обычно хорошо.

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

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

  • нужен доступ к полю извне его сборки, или
  • нужно прикрепить логику к геттеру / сеттеру

Сделай это:

  1. переименовать поле
  2. сделать это приватным
  3. добавить общедоступную собственность

Ваш клиентский код менять не нужно.

Однако когда-нибудь ваша система вырастет, и вы разложите ее на отдельные сборки и несколько решений. Когда это произойдет, любые открытые поля снова будут преследовать вас, потому что, как сказал Джефф, изменение общедоступного поля на общедоступное свойство - критическое изменение API.

Авто-свойства - такая же черная магия, как и все остальное в C#. Если вы подумаете об этом с точки зрения компиляции до IL, а не о его расширении до обычного свойства C#, это будет намного меньше черной магии, чем множество других языковых конструкций.

Я использую CodeRush, он быстрее авто-свойств.

Сделать это:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

Всего требуется восемь нажатий клавиш.

Если я зажму CTRL и V, я могу вставить много-много всего / очень быстро /, но это не делает его «лучше». Как это отвечает на исходный вопрос?

JBRWilkinson 18.02.2010 17:59

Что ж, с фрагментами кода одноименное автоматическое свойство будет состоять всего из семи нажатий клавиш;)

Одна вещь, о которой, кажется, никто не упомянул, - это то, что автоматические свойства, к сожалению, не полезны для неизменяемых объектов (обычно неизменяемых структур). Потому что для этого вам действительно нужно:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(где поле инициализируется в конструкторе с помощью переданного параметра, а затем доступно только для чтения.)

Таким образом, это имеет преимущества перед простым автосвойством get / private set.

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

Keith 13.02.2009 15:55

@Keith: Ваше первое предложение кажется фактически неверным.

Domenic 19.02.2009 00:27

@Domenic: Я думаю, он ограничивает свое определение структур неизменяемыми.

maxwellb 25.07.2009 05:39

Разве public string Title { get; private set; } не приведет к тому же результату? Конечно, вы могли бы изменить его изнутри класса, но если вы это сделаете, у вас будут другие проблемы ...: p

Svish 31.08.2009 12:14

Идея - защитное кодирование.

Domenic 01.09.2009 05:00

@Svish, это не совсем то же самое, потому что поле только для чтения может быть установлено только при построении или объявлении, где как частный сеттер может быть установлен и для неконструкторских методов в том же классе.

Zaid Masud 12.09.2011 01:56

@ zooone9243, Да, и, как я уже сказал, если мы не можем удержаться от установки значения внутри класса, которое должно быть неизменным, тогда у нас будут другие проблемы.

Svish 12.09.2011 11:47

@Svish: проблемы типа работы в команде, состоящей из программистов разного уровня подготовки?

Domenic 12.09.2011 17:04

@Svish - с помощью этого аргумента ключевое слово readonly в C# никогда не должно использоваться, потому что его использование будет означать, что мы скрываем эти «разные проблемы»

Zaid Masud 12.09.2011 19:55

@Domenic: Нет, проблемы вроде работы в команде, где разработчики делают то, чего делать не должны. Типа: «Эй, я знаю, что это должен быть неизменяемый объект, но давайте просто изменим эту переменную, чтобы заставить ее работать» - вроде того ...

Svish 13.09.2011 14:59

Я просто хочу сказать, что с точки зрения внешнего API это не будет иметь большого значения. Итак, при желании можно использовать автоматические свойства. Лучше всего, конечно, было бы, если бы вы могли сделать что-то вроде public string Title { get; private readonly set; }

Svish 13.09.2011 15:01

Иногда я разделяю типы .NET на две группы: типы, которые могут быть написаны на .NET (HttpRequest, Button), и те, которые могут быть написаны только под .NET и имеют «интерфейс» .NET, чтобы мы могли их использовать (object, Можно подумать, что Thread относится к более позднему типу. Что ж, это не так. Любой может переписать его на C#. Становится ясно, что поля только для чтения ДОЛЖНЫ быть обновляемыми в любой момент времени, потому что десериализация графа в противном случае потребовала бы магии, поскольку в общем случае нет определенной связи между параметрами ctor и полями только для чтения : BinaryFormatter

Eduard Dumitru 20.09.2013 02:31

@Domenic: Я не понимаю ... разве вы не можете сделать это с помощью авто-свойств ?:

public string Title { get; }

или же

public string Title { get; private set; }

Это то, о чем вы говорите?

Вы можете (последнее; первое не будет компилироваться), но тогда поле не будет неизменным внутри вашего объекта.

Domenic 20.09.2008 02:21

Предупреждение, только структуры являются неизменяемыми, если они отмечены только для чтения, классы просто не назначаются.

Guvante 08.10.2008 15:21

Это просто, это коротко, и если вы хотите создать реальную реализацию внутри тела свойства где-нибудь в конце строки, это не нарушит внешний интерфейс вашего типа.

Так просто.

От Бьярна Страуструпа, создателя 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 как зеленый свет для написания ужасно инкапсулированных (или вообще не инкапсулированных) классов, которые являются не более чем прославленным публичным полем. Конечно, это больше проблема с тем, как люди используют инструмент, а не с самим инструментом, но я думаю, что это важно упомянуть при обсуждении свойств в целом.

sara 03.09.2015 17:56

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

В VS2008 отсутствует рефакторинг Расчленить авто-свойство.

Тот факт, что у нас есть рефакторинг инкапсулировать поле, позволяет мне быстрее использовать только общедоступные поля.

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

Другие вопросы по теме