Почему мне следует избегать использования свойств в C #?

102

В своей прекрасной книге CLR Via C # Джеффри Рихтер сказал, что ему не нравятся свойства, и он рекомендует не использовать их. Он объяснил причину, но я не совсем понимаю. Может ли кто-нибудь объяснить мне, почему я должен или не должен использовать свойства? Изменилось ли это в C # 3.0 с автоматическими свойствами?

В качестве справки я добавил мнения Джеффри Рихтера:

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

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

• Свойство нельзя передать методу как параметр out или ref; поле может. Например, следующий код не будет компилироваться:

using System;
public sealed class SomeType
{
   private static String Name 
   {
     get { return null; }
     set {}
   }
   static void MethodWithOutParam(out String n) { n = null; }
   public static void Main()
   {
      // For the line of code below, the C# compiler emits the following:
      // error CS0206: A property or indexer may not
      // be passed as an out or ref parameter
      MethodWithOutParam(out Name);
   }
}

• Для выполнения метода свойства может потребоваться много времени; доступ к полю всегда завершается немедленно. Распространенной причиной использования свойств является выполнение синхронизации потока, которая может остановить поток навсегда, поэтому свойство не следует использовать, если требуется синхронизация потока. В этой ситуации предпочтительнее использовать метод. Кроме того, если к вашему классу можно получить удаленный доступ (например, ваш класс является производным от System.MashalByRefObject), вызов метода свойства будет очень медленным, и поэтому метод предпочтительнее свойства. На мой взгляд, классы, производные от MarshalByRefObject, никогда не должны использовать свойства.

• Если вызывается несколько раз подряд, метод свойства может каждый раз возвращать другое значение; поле каждый раз возвращает одно и то же значение. Класс System.DateTime имеет свойство Now только для чтения, которое возвращает текущую дату и время. Каждый раз, когда вы запрашиваете это свойство, оно будет возвращать другое значение. Это ошибка, и Microsoft желает, чтобы они могли исправить класс, сделав Now методом вместо свойства.

• Метод свойства может вызвать наблюдаемые побочные эффекты; доступа к полю никогда не бывает. Другими словами, пользователь типа должен иметь возможность устанавливать различные свойства, определяемые типом, в любом порядке, который он или она выбирает, не замечая какого-либо другого поведения в типе.

• Метод свойства может потребовать дополнительной памяти или вернуть ссылку на что-то, что на самом деле не является частью состояния объекта, поэтому изменение возвращенного объекта не влияет на исходный объект; запрос поля всегда возвращает ссылку на объект, который гарантированно является частью исходного состояния объекта. Работа со свойством, которое возвращает копию, может сбивать с толку разработчиков, и эта характеристика часто не документируется.

Куан Май
источник
11
У меня есть третье издание «CLR via C #», и на странице 242 г-н Рихтер говорит, что ему лично не нравятся свойства, но он никогда не рекомендует не использовать их. Укажите версию книги и номер страницы, на которой вы это читали.
kirk.burleson

Ответы:

173

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

Лично я не согласен с ним в этом конкретном вопросе - я считаю, что свойства делают клиентский код намного проще для чтения, чем эквивалентные вызовы методов. Я согласен с тем, что разработчики должны знать, что свойства - это в основном замаскированные методы, но я думаю, что лучше информировать разработчиков об этом, чем усложнять чтение кода с помощью методов. (В частности, увидев Java-код с несколькими геттерами и сеттерами, вызываемыми в одном операторе, я знаю, что эквивалентный код на C # будет намного проще читать. Закон Деметры очень хорош в теории, но иногда foo.Name.Lengthдействительно правильная вещь использовать ...)

(И нет, автоматически реализуемые свойства ничего из этого не меняют.)

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

Джон Скит
источник
Большое спасибо за ответ! О аргументах против использования методов расширения: вы говорите о какой-то теме Джеффри Рихтера или абстрактно?
Абатищев
@abatishchev: Это был просто общий момент о методах расширения. Это напрямую не связано со свойствами.
Джон Скит
Я бы пошел дальше. За исключением аспекта производительности, я не понимаю, почему программист должен ЗНАТЬ, является ли что-то полем или свойством. Он должен думать об этом как об атрибуте экземпляра, обозначающем STATE экземпляра объекта, а реализация объекта должна позаботиться обо всех изменениях его состояния (в рамках контракта класса). Таким образом, свойства могут быть полями в одних случаях или стать полями в других, если, возможно, будет произведен редизайн реализации класса. Тогда выбор между полем или имуществом - это вопрос того, какой уровень защиты нужен государству, чтобы оставаться последовательным.
TheBlastOne
1
@PatrickFromberg: Очевидно, вы пропустили большой объем кода, в котором используются поля только для чтения. Ничего не сказано, что свойства подразумевают изменчивость. У меня часто есть поля только для чтения, поддерживающие свойства только для чтения - как вы думаете, это плохо?
Джон Скит
1
@Patrick: Нет, это дает преимущество отделения API от реализации - позже вы можете изменить способ вычисления свойства из поля (например, для вычисления двух связанных свойств из одного поля).
Джон Скит
34

Что ж, давайте рассмотрим его аргументы один за другим:

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

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

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

Хотя это в основном так, вы вполне можете вызвать метод для неинициализированного поля объекта и вызвать исключение.

• Свойство нельзя передать методу как параметр out или ref; поле может.

Справедливая.

• Для выполнения метода свойства может потребоваться много времени; доступ к полю всегда завершается немедленно.

Это также может занять совсем немного времени.

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

Не правда. Как узнать, что значение поля не изменилось (возможно, другим потоком)?

Класс System.DateTime имеет свойство Now только для чтения, которое возвращает текущую дату и время. Каждый раз, когда вы запрашиваете это свойство, оно будет возвращать другое значение. Это ошибка, и Microsoft желает, чтобы они могли исправить класс, сделав Now методом вместо свойства.

Если это ошибка, то это мелкая ошибка.

• Метод свойства может вызвать наблюдаемые побочные эффекты; доступа к полю никогда не бывает. Другими словами, пользователь типа должен иметь возможность устанавливать различные свойства, определяемые типом, в любом порядке, который он или она выбирает, не замечая какого-либо другого поведения в типе.

Справедливая.

• Метод свойства может потребовать дополнительной памяти или вернуть ссылку на что-то, что на самом деле не является частью состояния объекта, поэтому изменение возвращенного объекта не влияет на исходный объект; запрос поля всегда возвращает ссылку на объект, который гарантированно является частью исходного состояния объекта. Работа со свойством, которое возвращает копию, может сбивать с толку разработчиков, и эта характеристика часто не документируется.

Большинство протестов можно сказать и о геттерах и сеттерах Java - и они у нас довольно долго были без таких проблем на практике.

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

Hejazzman
источник
3
«проблемы могут быть решены за счет лучшего выделения синтаксиса» : как часто вы используете общедоступные поля? Частные поля обычно имеют другой стиль, например _field. Или просто строчные field.
Стивен Джеурис
18

Я не читал книгу, а вы не процитировали ту ее часть, которую не понимаете, поэтому мне придется угадывать.

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

Если я печатаю Foo.Bar, люди, читающие его, обычно ожидают, что это просто доступ к полю-члену класса Foo. Это дешевая, почти бесплатная операция, и она детерминирована. Я могу повторять это снова и снова и каждый раз получать один и тот же результат.

Вместо этого со свойствами это может быть вызов функции. Это может быть бесконечный цикл. Это может открыть соединение с базой данных. Он может возвращать разные значения каждый раз, когда я к нему обращаюсь.

Это тот же аргумент, почему Линус ненавидит C ++. Ваш код может удивить читателя. Он ненавидит перегрузку операторов: a + bэто не обязательно означает простое добавление. Это может означать очень сложную операцию, как и свойства C #. Может иметь побочные эффекты. Он может делать что угодно.

Честно говоря, я считаю это слабым аргументом. Оба языка полны подобных вещей. (Следует ли избегать перегрузки операторов и в C #? В конце концов, там можно использовать тот же аргумент)

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

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

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

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

Свойства ... не могу.

Это отстой.

Но это не значит, что свойства - зло или их нельзя использовать. Для многих целей они великолепны.

Jalf
источник
3
Мой аргумент состоит в том, что вы не должны предполагать, что это поле для начала - потому что, если вы вызываете его из любого другого класса, у вас в любом случае не должно быть доступа к непостоянным полям, потому что они должны быть закрытыми. (Есть также соглашение об именах, чтобы проинформировать вас.)
Джон Скит,
1
Да я согласен. Аргумент, кажется, сводится к следующему: «Я привык, что этот синтаксис используется исключительно для полей. Поэтому распространять его на другие случаи - плохо». И очевидный ответ: «Ну, тогда привыкай к другим случаям, и будет неплохо». ;)
jalf
Я бы хотел, чтобы языки .net предоставляли стандартные средства, с помощью которых класс может отображать свойства как refпараметры; член (например Foo) формы void Foo<T>(ActionByRef<Point,T> proc, ref T param)со специальным атрибутом и преобразовать компилятор thing.Foo.X+=someVar;в Foo((ref Point it, ref int param)=>it.X += param, ref someVar);. Поскольку лямбда является статическим делегатом, закрытие не требуется, и пользователь объекта сможет использовать любое место хранения, поддерживающее свойство, как подлинный refпараметр (и может передать его другим методам в качестве refпараметра).
supercat
Написание лямбда-выражения вручную дает действительно неприятный на вид исходный код, но поэтому было бы полезно заставить компилятор выполнить преобразование. Код для класса, предоставляющего свойство "обратного вызова по ссылке", был бы довольно разумным. Единственный уродливый код (без преобразования) на стороне вызывающего.
supercat
Пожалуйста, поймите, что свойство - это вызов функции, замаскированный под член, поэтому его нельзя передать по ссылке больше, чем вы можете передать общедоступные функции класса. Вы всегда можете использовать публичный член, если вы намереваетесь это сделать. Свойство является интеллектуальным членом, оно может вызвать исключение для недопустимых данных, переданных для установки.
Diceyus
17

Еще в 2009 году этот совет выглядел просто как крик " Who Moved My Cheese". разновидности . Сегодня это почти до смешного устарело.

Один очень важный момент, который многие ответы, кажется, ходят на цыпочках, но не совсем затрагивают, заключается в том, что эти предполагаемые «опасности» свойств являются преднамеренной частью дизайна фреймворка!

Да, недвижимость может:

  • Укажите разные модификаторы доступа для геттера и сеттера. Это преимущество перед полями. Распространенным шаблоном является наличие общедоступного получателя и защищенного или внутреннего установщика, очень полезный метод наследования, который невозможно реализовать только с помощью полей.

  • Выбросить исключение. На сегодняшний день это остается одним из наиболее эффективных методов проверки, особенно при работе с UI-фреймворками, которые включают концепции привязки данных. Гораздо сложнее обеспечить, чтобы объект оставался в допустимом состоянии при работе с полями.

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

  • Возвращать разные значения из получателя при последующих выполнениях. Это почти похоже на шутку в такой непосредственной близости от точки, превозносящей достоинства параметров ref/ outс полями, чье значение поля после ref/out вызова почти гарантированно будет отличаться от его предыдущего значения, и это непредсказуемо.

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

  • Вызывают наблюдаемые побочные эффекты - именно поэтому свойства были изначально изобретены как языковая функция. Собственные правила Microsoft Property Design указывают, что порядок установки не имеет значения, иначе это будет означать временную привязку . Конечно, вы не можете добиться временной привязки только с полями, но это только потому, что вы не можете вызвать какое-либо значимое поведение с одними только полями, пока не будет выполнен какой-либо метод.

    Аксессоры свойств могут фактически помочь предотвратить определенные типы временной привязки, принудительно переводя объект в допустимое состояние до того, как будет предпринято какое-либо действие - например, если у класса есть a StartDateи an EndDate, то установка EndDateдо StartDateможет также принудительно выполнить StartDateобратное действие. Это верно даже в многопоточных или асинхронных средах, включая очевидный пример пользовательского интерфейса, управляемого событиями.

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

  • Ленивая загрузка - один из наиболее эффективных способов предотвращения ошибок порядка инициализации.
  • Уведомления об изменениях , которые в значительной степени составляют основу архитектуры MVVM .
  • Наследование , например определение абстрактных Typeили Nameпроизводных классов, может предоставить интересные, но, тем не менее, постоянные метаданные о самих себе.
  • Перехват , благодаря вышесказанному.
  • Индексаторы , которые каждый, кому когда-либо приходилось работать с COM-взаимодействием и неизбежным потоком Item(i)обращений, признает замечательную вещь.
  • Работайте с PropertyDescriptor, который необходим для создания дизайнеров и для фреймворков XAML в целом.

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

Я имею в виду, что его аргумент о том, что «свойства считаются вредными», по сути сводится к одному утверждению: свойства выглядят как поля, но они могут не действовать как поля. Проблема с этим утверждением в том, что оно не соответствует действительности или, в лучшем случае, сильно вводит в заблуждение. Свойства не выглядят как поля - по крайней мере, они не должны выглядеть как поля.

В C # есть два очень строгих соглашения о кодировании с аналогичными соглашениями, используемыми в других языках CLR, и FXCop будет кричать на вас, если вы не будете им следовать:

  1. Поля всегда должны быть частными, а не общедоступными.
  2. Поля следует указывать в camelCase. Свойства - это PascalCase.

Таким образом, нет двусмысленности в том, Foo.Bar = 42является ли метод доступа к свойству или методом доступа к полю. Это средство доступа к свойству, и с ним следует обращаться как с любым другим методом - он может быть медленным, генерировать исключение и т. Д. Такова природа абстракции - как реагировать полностью на усмотрение объявляющего класса. Разработчики классов должны применять принцип наименьшего удивления, но вызывающие не должны предполагать ничего о свойстве, кроме того, что оно делает то, что написано на банке. Это специально.

Альтернативой свойствам являются везде методы получения / установки. Это подход Java, и он с самого начала был неоднозначным . Ничего страшного, если это твоя сумка, но это не то, что мы делаем в лагере .NET. Мы пытаемся, по крайней мере, в рамках статически типизированной системы, избегать того, что Фаулер называет синтаксическим шумом . Нам не нужны лишние круглые скобки, лишние get/ setбородавки или дополнительные сигнатуры методов - если мы можем избежать их без потери ясности.

Говорите, что хотите, но foo.Bar.Baz = quux.Answers[42]это всегда будет намного легче читать foo.getBar().setBaz(quux.getAnswers().getItem(42)). И когда вы читаете тысячи строк этого текста в день, это имеет значение.

(И если ваш естественный ответ на предыдущий абзац - «конечно, его трудно читать, но было бы проще, если бы вы разбили его на несколько строк», то я с сожалением должен сказать, что вы полностью упустили суть .)

Aaronaught
источник
11

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

Автоматические свойства в C # 3+ лишь немного упрощают синтаксис (а-ля синтаксический сахар).

Константин Таркус
источник
пожалуйста, прочтите страницы 215-216 в этой книге. Я уверен, что вы знаете, кто такой Джеффри Рихтер!
Quan Mai,
Я прочитал (CLR через C #, 2-е изд.), Не согласен с его позицией и не вижу реальных причин не использовать свойства!
Абатищев
Это хорошая книга, но в данный момент я не согласен с автором.
Константин Таркус,
Где именно то место, где автор предлагает не использовать Properties? Не нашли ничего на стр.215-217
Константин Таркус
Я добавил в свой вопрос мнение Джеффри :). Вы можете найти его на страницах 215-216 в печатном издании :)
Куан Май
9

Это всего лишь мнение одного человека. Я прочитал довольно много книг по C # и еще не видел, чтобы кто-нибудь еще говорил «не использовать свойства».

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

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

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

Например

public class WorkerUsingMethod
{
   // Explicitly obvious that calculation is being done here
   public int CalculateResult()
   { 
      return ExpensiveLongRunningCalculation();
   }
}

public class WorkerUsingProperty
{
   // Not at all obvious.  Looks like it may just be returning a cached result.
   public int Result
   {
       get { return ExpensiveLongRunningCalculation(); }
   }
}

Я считаю, что использование методов для этих случаев помогает различать.

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

Допустим, у вас есть такая недвижимость:

public int Result 
{ 
   get 
   { 
       m_numberQueries++; 
       return m_result; 
   } 
}

Теперь предположим, что у вас есть исключение, которое возникает, когда делается слишком много запросов. Угадайте, что происходит, когда вы начинаете отладку и меняете свойство в отладчике? Плохие вещи. Избегайте этого! Просмотр свойства меняет состояние программы.

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

Марк Симпсон
источник
6

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

Рашак
источник
+1 за неявное подчеркивание важности «контракта» между клиентом и классовой недвижимостью.
TheBlastOne
6

Я не могу не обратить внимание на детали мнения Джеффри Рихтера:

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

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

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

Неправильно: реализация класса может изменить модификатор доступа к полю с публичного на частный. Попытки прочитать закрытые поля во время выполнения всегда приводят к исключению.

У Сесила есть имя
источник
5

Я не согласен с Джеффри Рихтером, но могу догадаться, почему ему не нравится недвижимость (я не читал его книгу).

Несмотря на то, что свойства аналогичны методам (с точки зрения реализации), как пользователь класса я ожидаю, что его свойства будут вести себя «более или менее» как публичное поле, например:

  • внутри геттера / установщика свойств не выполняется трудоемкая операция
  • геттер свойства не имеет побочных эффектов (вызов его несколько раз не меняет результат)

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

M4N
источник
1
+1, поскольку это подчеркивает важность чистого контракта. Свойство, которое, по-видимому, предназначено только для чтения, которое регулярно возвращает другое значение для каждой ссылки, является свойством readwrite - оно просто записывает не свое собственное значение, а другие переменные экземпляра (прямо или косвенно). Это неплохой стиль, но он должен быть задокументирован (или быть неявной частью контракта).
TheBlastOne
4

Бывает время, когда я не использую свойства, и это при написании кода .Net Compact Framework. Компилятор CF JIT не выполняет ту же оптимизацию, что и компилятор JIT для настольных компьютеров, и не оптимизирует простые средства доступа к свойствам, поэтому в этом случае добавление простого свойства приводит к небольшому раздутию кода из-за использования общедоступного поля. Обычно это не проблема, но почти всегда в мире Compact Framework вы сталкиваетесь с жесткими ограничениями памяти, поэтому даже такая крошечная экономия имеет значение.

Стив
источник
4

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

Однажды я увидел свойство, называемое чем-то вроде «Клиенты», которое внутренне открыло внепроцессный вызов базы данных и прочитало список клиентов. В клиентском коде был код for (int i to Customers.Count), который вызывал отдельный вызов базы данных на каждой итерации и для доступа выбранного клиента. Это вопиющий пример, демонстрирующий принцип очень легкого использования свойства - редко больше, чем доступ к внутреннему полю.

Одним из аргументов ЗА использование свойств является то, что они позволяют проверить установленное значение. Другой заключается в том, что значением свойства может быть производное значение, а не отдельное поле, например TotalValue = количество * количество.

Роб Кент
источник
3

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

Стив
источник
3

Аргумент предполагает, что свойства плохие, потому что они выглядят как поля, но могут выполнять неожиданные действия. Это предположение опровергается ожиданиями .NET-программистов:

Свойства не похожи на поля. Поля выглядят как свойства.

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

Итак, поле похоже на свойство, которое гарантированно никогда не вызовет исключения.

• Свойство нельзя передать методу как параметр out или ref; поле может.

Итак, поле похоже на свойство, но у него есть дополнительные возможности: переход к ref/ outпринимающим методам.

• Для выполнения метода свойства может потребоваться много времени; доступ к полю всегда завершается немедленно. [...]

Итак, поле похоже на быстрое свойство.

• Если вызывается несколько раз подряд, метод свойства может каждый раз возвращать другое значение; поле каждый раз возвращает одно и то же значение. Класс System.DateTime имеет свойство Now только для чтения, которое возвращает текущую дату и время.

Итак, поле похоже на свойство, которое гарантированно возвращает одно и то же значение, если для поля не задано другое значение.

• Метод свойства может вызвать наблюдаемые побочные эффекты; доступа к полю никогда не бывает.

Опять же, поле - это свойство, которое гарантированно этого не делает.

• Метод свойства может потребовать дополнительной памяти или вернуть ссылку на что-то, что на самом деле не является частью состояния объекта, поэтому изменение возвращенного объекта не влияет на исходный объект; запрос поля всегда возвращает ссылку на объект, который гарантированно является частью исходного состояния объекта. Работа со свойством, которое возвращает копию, может сбивать с толку разработчиков, и эта характеристика часто не документируется.

Это может показаться удивительным, но не потому, что это делает свойство. Скорее всего, почти никто не возвращает изменяемые копии в свойствах, так что случай 0,1% вызывает удивление.

тысячелетний жук
источник
0

Вызов методов вместо свойств значительно снижает удобочитаемость вызывающего кода. Например, в J # использование ADO.NET было кошмаром, потому что Java не поддерживает свойства и индексаторы (которые по сути являются свойствами с аргументами). Полученный код был крайне уродливым, с повсюду вызовами методов в круглых скобках.

Поддержка свойств и индексаторов - одно из основных преимуществ C # над Java.

Марти Соломон
источник