c # используя сеттеры или геттеры из базового класса

Рекомендуется ли устанавливать переменные-члены базового класса для защищенных, чтобы подклассы могли обращаться к этим переменным? Или более рекомендуется установить переменные-члены в private и позволить подклассам получать или устанавливать переменные с помощью методов получения и установки?

И если рекомендуется использовать метод getters и setters, когда используются защищенные переменные?

12.12.2008 13:24:07
4 ОТВЕТА
РЕШЕНИЕ

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

Лично мне не нравится, чтобы какие-либо поля были не приватными, за исключением случайных исключений статических полей только для чтения с неизменяемыми значениями (постоянными или нет). Для меня свойства просто дают лучшую степень инкапсуляции. То, как хранятся данные, является решением о реализации , а не решением API (в отличие от свойств). Почему класс Foo, производный от класса Bar, должен заботиться о реализации класса Bar?

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

Благодаря автоматически реализованным свойствам в C # 3.0 легче, чем когда-либо, превратить поля в свойства. Есть маленькая причина не делать этого.

14
23.05.2017 12:04:26

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

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

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

РЕДАКТИРОВАТЬ: Я сделал некоторые профилирования и, по-видимому, даже в режиме выпуска может быть до 20% разницы в скорости между полями и свойствами. Смотрите мой тестовый пример здесь: http://pastebin.com/m5a4d1597

0
12.12.2008 13:56:14
Если в свойстве нет логики, в режиме выпуска JIT все равно будет включать доступ к свойству, поэтому не должно быть никакого снижения производительности.
Jon Skeet 12.12.2008 13:36:46
Я подробно описал это; нет потери производительности с прямыми (тривиальными) свойствами; в некоторых тестах это действительно становилось быстрее, но я подозреваю, что космические лучи мешали тесту ;-p
Marc Gravell♦ 12.12.2008 13:37:27
Я попробовал ваш тест (используя секундомер и 10-кратные итерации, чтобы получить лучшее время). Я не вижу разницы в 20%, но я вижу изменение примерно на 5%, что меня удивляет. Рассматривая это больше ...
Jon Skeet 12.12.2008 14:11:42
@ Грег: Я думаю, что тест в основном разумный. То, что есть способы ускорить его, не означает, что это не представляет интереса. Компилятор должен иметь возможность вставлять свойства независимо. Я попытался сделать поля приватными, а свойства не ускорились.
Jon Skeet 12.12.2008 14:16:07
(Я еще не пробовал запечатывать класс. Это, безусловно, интересно. Сейчас я пытаюсь использовать целые числа вместо двойных.)
Jon Skeet 12.12.2008 14:16:58

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

2
12.12.2008 13:41:58

Я должен согласиться с Джоном.

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

Но set / get это способ сделать для другой ситуации.

0
12.12.2008 13:46:25
Он не имеет такой же инкапсуляции - он указывает, что сейчас и навсегда эти данные будут храниться в поле с таким именем. Любое изменение в этом решении по реализации является серьезным изменением. Часто с этим можно жить, но я предпочитаю этого не делать :)
Jon Skeet 12.12.2008 13:57:21
Да, то же самое верно и для имени Геттера;) Я предпочитаю нет, но я думаю, что в некоторых случаях это не так уж и плохо, делать это;)
Patrick Desjardins 12.12.2008 14:39:17
Однако я бы сказал, что имя получателя является частью API, тогда как выбор хранилища - это проблема реализации.
Jon Skeet 12.12.2008 15:18:05