Действительно ли защищенные члены/поля действительно так плохо?

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

Я могу это видеть, если вам нужно убедиться, что некоторые проверки проверки выполняются при получении/настройке значения, однако, много времени, по моему мнению, это просто дополнительные накладные расходы. Я имею в виду, скажем, у меня есть класс GameItem с полями для baseName, prefixName и suffixName. Почему я должен взять накладные расходы как для создания свойств (C#), так и для методов доступа, а также для производительности, которое я бы повредил (если я делаю это для каждого отдельного поля в приложении, я уверен, что он будет складываться при меньшем количестве немного особенно на некоторых языках, таких как PHP, или некоторые приложения с производительностью критичны как игры)?

Ответ 1

Являются ли защищенные члены/поля действительно такими плохими?

Нет. Они дороги, хуже.

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

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

лучший способ совместного использования информации с производными классами - это свойство только для чтения:

protected object MyProperty { get; }

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

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

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

Ответ 2

ОК, время вниз.

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

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

Остальные аргументы беспокоят меня таким образом:

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

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

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

Ответ 3

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

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

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

Относительно накладных расходов:

  • Если геттер/сеттер является обычным одним фрагментом кода, который просто считывает/устанавливает значение поля, тогда JIT должен иметь возможность встроить вызов, поэтому нет превышения производительности.

  • Синтаксические накладные расходы в значительной степени уменьшаются при использовании автоматически реализованных свойств (С# 3.0 и новее), поэтому я не думаю, что это проблема:

    protected int SomeProperty { get; set; }
    

    Фактически, это позволяет вам легко сделать, например, set protected и get public, поэтому это может быть даже более элегантным, чем использование полей.

Ответ 4

Открытые и/или защищенные поля являются плохими, потому что их можно манипулировать вне класса объявления без проверки; таким образом, можно сказать, что они нарушают принцип инкапсуляции объектно-ориентированного программирования.

Когда вы теряете инкапсуляцию, вы теряете контракт объявляющего класса; вы не можете гарантировать, что класс ведет себя так, как предполагалось или ожидалось.

Использование свойства или метода доступа к полю позволяет поддерживать инкапсуляцию и выполнять контракт объявляющего класса.

Ответ 5

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

Но когда я на работе, это другая история.

Ответ 6

Это на самом деле зависит от того, является ли ваш класс классом данных или классом поведения.

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

Если класс является классом поведения, то он не должен предоставлять никаких данных.