Подтвердить что ты не робот

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

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

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

и

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

?

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

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

EDIT: Спасибо всем за ответ! Для меня это было действительно информативно; чтобы подвести итог тому, что я собрал/узнал из всего сказанного, следующие несколько выводов, которые я сделал до сих пор:

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

try { var ignored = customer.Name; }
catch { Assert.Fail("Exceptions are not expected"); }

Ответ 5

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

  • Они могут быть показаны и отредактированы в Property Grid. Без свойств, как бы вы знали, какие методы показывают редакторы?
  • Они предлагают намек на то, что что-то дешево читать и писать, и что чтение не вызывает побочных эффектов. (Можно, конечно, нарушить это, но, создав что-то свойство, вы заявляете, что это ваше намерение.) Поэтому отладчик может принять этот намек. Если вы наведите указатель мыши на свойство, отладчик покажет его значение в всплывающей подсказке. Не имеет смысла делать то же самое для любого возможного метода; слишком легко случайно сделать что-то с побочными эффектами.

Ответ 6

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

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

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

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

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

Ответ 7

Свойства в сущности - это пары get/set.

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

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

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

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

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

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

Ответ 8

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

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

против

obj.Value++;

Ответ 9

для меня это легко:

myprop = myvalue;
console.writeline(myprop);

нет необходимости

mysetfunc(myvalue);
console.writeline(mygetprop);

легче запомнить 1 вещь, чем 2

Ответ 10

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

Ответ 11

Может быть, небольшая точка, но с геттерами/сеттерами мне нахожу, что это раздражает, что, когда я еду через них в среде IDE с "intellisense", там находится массивный блок "геттеров" рядом друг с другом и еще один блок "сеттеров" ". Мне труднее найти то, что я ищу.

Ответ 12

С методами 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;

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

Ответ 13

Как usr говорится:

"Свойство имеет смысл получить без побочных эффектов и получить и установить быструю операцию."

Совершенно верно. Подразумевается, что геттер/сеттер будет быстрым. Выставляя что-то как свойство, вы подразумеваете, что вы быстро извлекаете/помещаете атрибут на объект. Методы для выполнения той или иной формы работы предполагаются задействованными больше циклов, чем просто получение/установка атрибута. Обычно мы добавляем длинные операции "свойства" в методы GetFoo (...)/SetFoo (...), чтобы указать, что операция вычисления тяжелее, чем свойство.

Ответ 14

По крайней мере для DataBinding
Развитие UI становится более сложным без него.

Ответ 15

Они позволяют пользователю типа иметь упрощенный синтаксис и позволяют создавать поля только для чтения и только для записи. таким образом me.SetAge(34); age = me.GetAge(); становится me.age = 34; age = me.age;