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

Примечание: это было опубликовано, когда я только начинал изучать C#. Обладая знаниями 2014 года, я действительно могу сказать, что автоматические свойства - это одно из лучших вещей, которые когда-либо происходили с языком C#.

Я привык создавать свои свойства на C#, используя частное и общедоступное поля:

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

Теперь, с .NET 3.0, мы получили автоматические свойства:

public string Title { get; set; }

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

Фактически, скрытое частное поле даже не отображается в отладчике, что нормально, учитывая тот факт, что функции get / set ничего не делают. Но когда я действительно хочу реализовать некоторую логику геттера / сеттера, мне все равно приходится использовать частную / общедоступную пару.

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

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

Ответов (18)

Решение

Мы постоянно используем их в Stack Overflow.

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

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

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

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

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

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

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

public string Title { get; }

или

public string Title { get; private set; }

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

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

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

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

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

Я постоянно использую автоматические свойства. До C# 3 я не мог утруждать себя набором текста и вместо этого просто использовал общедоступные переменные.

Единственное, чего мне не хватает, так это возможности сделать это:

public string Name = "DefaultName";

Вы должны перенести значения по умолчанию в свои конструкторы со свойствами. скучный :-(

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

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

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

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

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

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

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"; }

В неизменяемых классах с большим количеством членов это позволяет сэкономить много лишнего кода.

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

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

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

Сделай это:

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

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

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

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

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

Сделать это:

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

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

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

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

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

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

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

Так просто.

От Бьярна Страуструпа, создателя C++:

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

И знаешь, что? Он прав. Как часто вы просто обертываете частные поля в get и set, фактически ничего не делая внутри get / set, просто потому, что это «объектно-ориентированное» действие. Это решение проблемы Microsoft; это в основном общедоступные поля, к которым вы можете привязаться.

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

В VS2008 отсутствует рефакторинг Explode Auto-Property .

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

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