Почему даже можно изменить частный член или запустить частный метод в С# с помощью отражения?

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

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

Если вы установите для параметра field/member/method как private/internal, почему С# в качестве языка разрешает устанавливать эти поля вне области видимости? Я бы подумал, что это вызовет какое-то исключение. Если класс хотел, чтобы они были изменены или установлены, не было бы метода или конструктора?

Ответ 1

Поскольку существуют модификаторы доступа, которые помогут вам документировать API, который вы хотите предоставить потребителям или наследникам и т.д.

Они не являются механизмом контроля безопасности/доступа.

Ответ 2

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

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

Ответ 3

Частное размышление требует, чтобы вы получили по существу полное доверие. Полное доверие означает полное доверие. Если вам полностью доверяют делать правильные вещи, то почему это не должно работать?

(На самом деле, модель безопасности для частного отражения на самом деле намного сложнее, чем я нарисовал ее здесь, но это не влияет на мою точку зрения: эта способность подчиняется политике. См. Вопросы безопасности для отражения (MSDN) для обзора того, как взаимодействуют политика отражения и безопасности.)

Ответ 4

Модификаторы видимости не предназначены для безопасности.

Они просто предназначены для того, чтобы сделать работу с структурированными API/кодами более эффективными - чтобы не заглушить программиста с помощью guff - и только разоблачить то, что потребители должны заботиться.

Ответ 5

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

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

Ответ 6

Иногда вам приходится обманывать.

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

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

Следует отметить, что С++ и его производные имеют сильный контроль доступа, но есть много языков ООП, которые этого не делают. Например, объекты Perl 5 полностью открыты для внешних помех, а частные методы и данные существуют только по соглашению - программист Perl знает, что беспорядок внутри стороннего объекта hashref, вероятно, будет нарушать вещи, поэтому они обычно выигрывают Не делай этого. Опять же, как и с возможностями С# отражения, иногда вы можете решить множество проблем с небольшой настройкой на то, что вы на самом деле не должны касаться.

Но я повторяю еще раз, вы почти наверняка не должны этого делать. Эти возможности не предназначены для повседневного использования.

Ответ 7

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

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

Рентген (или что-то tomography-like) может наблюдать за мной, что я никогда не могу без него.

1kUml.jpg

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

Таким образом, отражение должно быть связано с реалистичным, без определенного взгляда. И вы можете предположить, что код потребителей ограничен BindingFlags.Public, в рамках правил объектной ориентации.

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

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

Ответ 8

Хороший вопрос.

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

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

И если бы этот низкий уровень доступа к отражению НЕ был возможен, многие вещи, которые мы все узнали и как, были бы практически невозможны.

Ответ 9

Случай в производственном коде:

Мы хотели, чтобы один веб-сервис работал в часовом поясе NZ. Вероятно, правильным решением является переписать весь наш код (включая некоторый код сериализации .NET Framework) для использования DateTimeOffset, но самым простым решением было эффективно настроить два частных поля в .NET Framework, которые хранят текущий часовой пояс (обычно основанный при вызове реестра), чтобы явно использовать часовой пояс NZ.

Мы знаем, что если .NET Framework версии 2.0 постоянно обновляется при обработке часовых поясов, нам, возможно, придется переработать наш код, но на данный момент это отлично работает в производстве.