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


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

В случае свойства, скажем public string DataAsString, средство доступа get будет содержать логику для кодирования всех данных в строку, в то время как средство доступа set будет декодировать входное значение и устанавливать все данные в экземпляре класса. Это кажется удобным, потому что вход/выход действительно является строкой.

В случае метода одним из методов будет Encode(), который возвращает закодированную строку. Тогда либо конструктор сам бы разместил логику для декодирования строки и потребовал бы строковый аргумент, или я пишу метод Decode(string str), который вызывается отдельно. В любом случае он будет использовать метод вместо свойства.

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

6 3

6 ответов:

Нет никакой функциональной разницы; свойства-это просто пары методов get и set с точки зрения поведения.

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

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

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

"глаголы: методы должны работать и иметь побочные эффекты.

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

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

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

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

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

Возьмем для примера класс Person Человек.Название имеет смысл, так как собственность в данном случае. Человек.Speak () не имеет смысла как свойство.

Все зависит от того, какую функцию он выполняет.

Еще один не упомянутый момент заключается в том, что если одно или несколько свойств чтения-записи объекта записываются, а затем все они считываются без каких-либо промежуточных вызовов метода, то считанные значения должны соответствовать записанным значениям. Если запись свойства Foo приведет к изменению значения свойства read-write Bar, это, на мой взгляд, будет хорошим признаком того, что тот или иной метод должен быть парой явных методов getter-setter, а не свойством. Существует множество классов в .net, которые нарушают это принцип, но я считаю такое поведение небрежным. Возможно, самым страшным преступником является видимое свойство контроля. Запись свойства обновляет поле, состояние которого не может быть прочитано, в то время как чтение свойства возвращает результат некоторых вычислений. Лучше было бы иметь скрытое свойство для чтения и записи и видимое поле только для чтения. Кстати, на немного похожей ноте я бы сделал свойство "Length" StringBuilder доступным только для чтения, но имел методы для его усечения или заполнения; только свойство чтения-записи, которое у меня было бы, было бы значением.