Почему мы используем свойства .NET вместо простых старых функций get / set? - PullRequest
17 голосов
/ 19 июня 2009

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

public int NormalClass::getQuality() {
    return this->quality;
}

и

protected void NormalClass::setQuality(int q) {
    this->quality = q;
}

Какие дополнительные преимущества предлагает свойства .NET, помимо эстетики?

Я приму «читабельность», если вы сможете привести веские аргументы в пользу этого; но лично я склонен думать, что функция get / set более читаема, чем свойство, поскольку она однозначно является функцией , а не прямым значением.

РЕДАКТИРОВАТЬ: Спасибо всем за ответы! Это было действительно информативно для меня; Подводя итог тому, что я собрал / узнал из всего сказанного, приведу несколько выводов, к которым я пришел:

  • Наибольшие преимущества свойств исходить не из особенностей сами свойства, а точнее от фреймворка и возможностей IDE, которые обрабатывать свойства особым образом; например, редактор свойств, XML сериализация, привязка данных.
  • Свойства можно рассматривать как простые значения определенными удобными способами что получить / установить функции не могут: в в частности, obj.Prop ++ и obj.Prop = значение.
  • Свойства позволят вам уйти с быстрым и грязным кодом, используя публичные участники без прохождения головная боль реализации связки функции get / set позже; если ты когда-нибудь нужно будет добавить немного логики и / или сделать публичного члена частным, Вы можете просто ввести свойство и не рискуйте нарушать любой старый код.

Итак, есть один момент, который был сделан в 2 или 3 ответах, так что я лично нахожу несколько сомнительным: свойства подразумевают недорогие операции чтения / записи и поэтому могут использоваться по существу так же, как и простые переменные. Моя проблема с этим моментом заключается в том, что нет ничего, присущего свойствам, которые фактически обеспечивают это; это просто, как они предполагается , которые будут использоваться. На мой взгляд, это аналог квалификатора shouldBePrivate, который указывает, что значение следует напрямую доступно только его собственному классу, но к нему все равно можно получить доступ извне; или полицейские силы, которые патрулируют улицы, чтобы напомнить нам, что мы должны вести себя сами, но на самом деле не вмешиваются, когда мы начинаем совершать преступления (если это не применяется, что это на самом деле делает для нас?) .

Я был бы более впечатлен этим моментом, если бы в свойствах был какой-то встроенный механизм для обеспечения дешевизны чтения / записи.

Ответы [ 15 ]

24 голосов
/ 20 июня 2009

Джон Скит (Jon Skeet) имеет отличный обзор в своем блоге на C # о почему свойства имеют значение В нем он объясняет, почему свойства должны использоваться поверх открытых полей.

Что касается использования свойств вместо методов получения / установки, я бы предложил следующие соображения:

  • Свойства обеспечивают более чистый и краткий синтаксис, который легко понять и прочитать.
  • Свойства включают цепочку выражения присваивания: A.x = B.y = C.z
  • Свойства четко и последовательно передают семантику доступа к данным - потребители ожидают, что побочных эффектов не будет.
  • Свойства распознаются многими библиотеками в .NET для таких задач, как сериализация XML, привязки WPF, двусторонняя привязка ASP.NET и т. Д.
  • Свойства распознаются IDE и многими визуальными дизайнерами и могут отображаться в редакторе свойств.
  • Свойства включают поддержку операторов увеличения (++) и уменьшения (-).
  • Свойства можно легко отличить от методов, использующих отражение, и позволяют динамическим потребителям извлекать знания о данных, представленных объектом.
  • C # 3 поддерживает автоматические свойства, которые помогают исключить шаблонный код.
13 голосов
/ 19 июня 2009

Свойства (особенно автоматические свойства в .net 3.5) более кратки, чем сеттеры / геттеры, и меньше строк кода == меньше кода для поддержки == меньше ошибок.

Сначала я бы сказал, что удобочитаемость, но вы уже сказали, что это не считается для вас ..:)

10 голосов
/ 19 июня 2009

Я считаю, что XML-сериализация только читает / записывает открытые свойства, поэтому ваши методы get и set будут игнорироваться.

Кроме того, если у вас есть общий список объектов, вы можете назначить его для DataGridView.DataSource, и вы получите столбец для каждого из ваших свойств. Это может быть то, на что ссылался @LPalmer.

7 голосов
/ 19 июня 2009

Наличие свойств не только в языке, но и в clr означает, что каждый в .NET может положиться на свои метаданные. Свойство имеет коннотацию get без побочных эффектов, а get и set являются быстрой операцией. Многие инструменты используют это предположение: конструктор winforms, LINQ to SQL ...

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

Вот другие типичные предположения:

customer.Name = "a";
Assert.IsTrue(customer.Name == "a");

try { var ignored = customer.Name; }
catch { Assert.Fail("Exceptions are not expected"); }
4 голосов
/ 19 июня 2009

Одним из популярных способов взглянуть на объектно-ориентированное программирование является моделирование классов в наших программах на основе концепций в наших головах.

Концепции в наших головах основаны на реальных объектах, которые мы воспринимаем вокруг нас (воспринимаем ли мы их или общаемся с другими, кто их воспринимал).

Объекты вокруг нас - мебель, животные, космические челноки и т. Д. - обладают особыми свойствами и действуют определенным образом.

Вот где мы получаем свойства и методы.

В C # свойство не может быть приведено к одному полю-получению или набору полей (например, может потребоваться дополнительная проверка или может быть задействовано кэширование или любое количество причин). Поэтому нам нужна отдельная концепция свойств с get-методами и set-методами, чтобы наши программы стали ближе к концепциям, которые мы хотим, чтобы они моделировали.

4 голосов
/ 19 июня 2009

Два больших преимущества для свойств:

  • Они могут быть показаны и отредактированы в таблице свойств. Без свойств, как вы узнаете, для каких методов показывать редакторы?
  • Они предлагают намек на то, что что-то дешево читать и писать, и что чтение не вызывает побочных эффектов. (Конечно, это можно нарушить, но, сделав что-то свойством, вы заявляете, что это ваше намерение.) Следовательно, отладчик может принять эту подсказку. Если навести указатель мыши на свойство, отладчик покажет его значение во всплывающей подсказке. Не имеет смысла делать то же самое для любого возможного метода; слишком легко случайно что-то сделать с побочными эффектами.
3 голосов
/ 19 июня 2009

Помимо семантической правильности использования свойств для значения, которое описывает свойство объекта, с этим не поспоришь:

obj.SetValue(obj.GetValue() + 1);

против

obj.Value++;
3 голосов
/ 19 июня 2009

Свойства сущности являются парами методов получения / установки.

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

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

Я склонен думать, получить / установить функция более читабельна, чем свойство, так как это однозначно функция в отличие от прямой значение.

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

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

  • Примечание: не все свойства дешевы, но общие правила гласят, что они должны быть максимально простыми и легкими.
2 голосов
/ 20 июня 2009

С помощью методов get и set вы должны решить использовать их с самого начала и почти всегда писать много шаблонного кода для каждого открытого свойства, которое предоставляют ваши классы.

class Point
{
    private int x, y;

    // Ew, pointless boilerplate!
    public int  getX()      { return x;   }
    public void setX(int x) { this.x = x; }

    public int  getY()      { return y;   }
    public void setY(int y) { this.y = y; }
}

// ...

Point p = new Point();
p.setX(5);
p.setY(10);

С помощью свойств вы можете исключить шаблон геттеров и сеттеров для 90% свойств, которые имеют только тривиальные геттеры и сеттеры. Вы можете просто выставить открытые переменные напрямую

class Point
{
    public int x, y;
}

Point p = new Point();
p.x = 5;
p.y = 10;

Затем, если вы решите, что хотите добавить какое-либо поведение к вашим публичным переменным, вы можете переключить их на свойства с реальным поведением в методах get или set. Положительным моментом здесь является то, что пользователи вашего класса вообще не подвержены влиянию. Ничего не изменилось; им не нужно переключаться с point.x = 5 на point.setX(5). Ваш общедоступный интерфейс стабилен , что позволяет вам сначала использовать простые переменные и переключаться на более медленные get / set методы позже, когда вы добавляете некоторую защиту / ведение журнала / что угодно.

class Point
{
    public int x { get; set; }
}

// No change! 
Point p = new Point();
p.x = 5;
p.y = 10;

(Теперь, строго говоря, ваш синтаксический интерфейс не изменился, но скомпилированный интерфейс вашего класса изменился, поэтому вам придется перекомпилировать весь код, который использует ваш класс, если вы переключаетесь с переменных на свойства. Вы не можете получить скажем, просто перекомпилируйте свой класс и удалите его вместо старого класса, если ваш класс является частью широко используемой библиотеки. Пользователям вашей библиотеки придется перекомпилировать свой код в соответствии с новой версией вашей библиотеки.)

2 голосов
/ 19 июня 2009

Может быть, незначительный момент, но с геттерами / сеттерами меня раздражает то, что, когда я циклически перебираю их в IDE с 'intellisense', рядом друг с другом находится массивный блок 'геттеров' и еще один блок 'сеттеров' ». Мне сложнее найти то, что я ищу.

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