为什么甚至可以更改私有成员,或者使用反射在C#中运行私有方法?

Rya*_*ost 89 .net c# reflection

我最近遇到了一个问题,我使用的是C#,它是通过使用反射设置一个私有成员来解决的.

我惊呆了,发现设置私有成员/字段并运行私有方法是C#中允许和可能的事情.这不是一个如何做这些事情的问题,他们有很好的记录,我的问题是:为什么?

如果将字段/成员/方法设置为私有/内部,为什么C#作为一种语言允许将这些字段设置在范围之外?我认为这会抛出某种异常.如果类要求更改或设置它们不会有方法或构造函数?

Dam*_*ver 133

因为访问修饰符可以帮助记录您要向消费者或继承者等公开的API .

它们不是安全/访问控制机制.

  • @Patashu即使那个不存在,你仍然可以调用,例如,C++代码可以在流程的内存中的任何地方徘徊.在一天结束时,你无法阻止程序操纵它自己的内存空间; 为了能够发挥作用,它需要有足够的访问权来完成它想要的任何内存. (8认同)
  • 我不认为访问修饰符不是安全访问控制机制是完全公平的,尽管它们不提供OP讨论的类型的安全性.请参阅[访问级别和修饰符(私有,密封等)是否在C#中用作安全目的?](http://stackoverflow.com/q/891018/18192).Per Eric Lippert:"访问限制可以缓解部分受信任的恶意代码对用户的攻击." (6认同)
  • 我认为关键字`unsafe`的存在意味着即使Reflection不存在,您也可以访问C#数据类型的私有字段.(我不是想玩的游戏) (3认同)

Ser*_*rvy 64

阻止某人做到这一点是不可能的.你可以让它变得更难,你可以强迫他们使用不安全的代码并开始盲目地设置位.毕竟,这是他们的程序/机器,他们被允许做这样的事情.

语言的设计使你很难在脚下拍摄并做坏事.但这并不能使它们变得不可能,这样做也会限制用户做一些不寻常但仍然可取的事情.

  • 这是我最喜欢的答案.修改值只是一种访问内存的机制 - 因为大规模的*病毒预防/清除*市场.这个想法是,如果你让消费者看不到一些东西,他们就会意识到*一般来说*就是应该如何使用界面**.**这也意味着通过`Reflection`修改数据可能会导致不稳定*(尽管我已经做完了)*:D (11认同)
  • 这不是不可能的.真的很难.例如,您可以运行一个程序,以便拦截每个内存访问(使用mmu),并通过单独的进程(使用调试API)或通过内核或某种类型的vm监视器进行验证.这样的监控程序可以内省访问内存并做出非常复杂的策略决策.这将是超级慢,但它是可能的. (2认同)

Eri*_*ert 56

私人反思要求您获得基本上完全信任.完全信任意味着完全信任.如果你完全信任做正确的事情,为什么不应该这样做?

(事实上​​,私有反射的安全模型实际上比我在这里描绘的要复杂得多,但这并不影响我的观点:这种能力受制于政策.请参阅反思的安全注意事项(MSDN)以获得概述反思和安全政策如何相互作用.)


Dav*_*ish 14

可见性修饰符不是为了安全.

它们只是意味着使结构化API /代码库的使用更加有效 - 不会让程序员陷入困境 - 并且只暴露消费者应该关注的事情.


15e*_*153 6

反思是你如何与编译的代码进行交互.如果反思尊重源语言对隐私的期望,那么就需要另一种机制,就像它没有那样.海龟一路下来.

首先假设它的作用是它的意图,然后重新评估你的假设,即做一些不同的事情是一种误导的努力,无论如何都没有人想做.


Mat*_*ton 5

有时,你必须作弊.

很容易说,如果需要设置类,那么该类应该有一个setter,但如果你不能添加一个呢?如果它不是你的课程,它是一个专有的库,你需要解决其中的错误怎么办?我并不是说你应该做这些事情,事实上我会说你几乎肯定不应该,但有时候让事情发挥作用的唯一方法就是作出无耻的欺骗.在这些情况下,存在这些机制的事实非常有用.

但是,您应该始终质疑它们的使用,当然要注意,违反对象的公共API可能会导致问题进一步发生,并且可能是错误的做法.除了在前面提到的场景中,这是你可以在某些代码中使某些东西无法改变的唯一方法.

需要注意的一点是,C++及其衍生产品具有强大的访问控制能力,但是有很多OOP语言没有.例如,Perl 5对象完全对外部干扰开放,私有方法和数据只是按照惯例 - Perl程序员知道弄乱第三方对象的hashref可能会破坏事物,所以他们通常会赢那样做.同样,就像C#的反射功能一样,有时你可以通过对你不应该触摸的东西进行一些调整来解决很多问题.

但我再说一次,你几乎肯定不应该这样做.这些功能不适合日常使用.


Ken*_*Kin 5

没有反光的东西,我甚至看不到我的脸.好吧,我可以在视频中观看自己,但这是通过称为相机的光学设备完成的,而且它也是使用反射技术的东西.

如果我生病了,当医生需要X光来诊断和治疗我的疾病时,我可能已经死了,但是各种各样的反思都无法看出我的私密性.我再也看不到自己了.

X射线(或类似断层扫描的东西)可以看到我的内心,没有它我永远无法做到.

1kUml.jpg

我宁愿说它比反思更现实.但是,是的,我不能用眼睛直接看到真实的我,每一个我见过的人,都是某种反思.(要深入思考,眼睛也会给我们现实的反映.)

因此,反思应该与现实相关,没有特定的观点.并且您可以假设消费者代码仅限于面向对象规则中的BindingFlags.Public.

在真实的宇宙中,几乎没有什么是不可能的; 我们可能和不可能之间的唯一区别在于它是否可以由人类完成,因为我们是人类.

反射可以在程序世界中完成所有事情似乎是危险的,现在,出于安全原因,人类的逻辑需要完全信任它.