反思:使用反思仍然是“坏”还是“慢”?自2002年以来,反思发生了什么变化?


21

我已经注意到在处理表达式或表达式树时,我经常使用反射来设置和获取属性以及您所拥有的值。在我看来,反射的使用似乎越来越普遍。诸如用于验证的数据注释,属性繁重的ORM等之类的东西。我想知道:自从几年前和几年前我被告知尽可能避免反思以来,发生了什么变化?

那如果发生了什么变化呢?仅仅是机器的速度吗?是否对框架进行了更改以加快反思?

还是什么都没有真正改变?使用反射还是“不好”还是“慢”?


2
反射总是比直接调用慢,因为您必须执行几个步骤才能找到并验证您正在调用的内容是否存在。
Michael K'4

这总是很糟糕的。...当然,有时候您别无选择,这取决于程序员知道什么时候出现,否则请避免。
Ramhound 2012年

使用gettype进行反射以将枚举中的一项提取到使用Enum.Parse()引发异常仍然要快30倍以上。因此,反思有时会赢。
Brain2000 '18

Answers:


16

反思既不坏也不慢。它只是一个工具。像所有工具一样,它在某些情况下非常有价值,而在其他情况下则不那么有价值。

如果确实存在性能问题,则可以始终使用FasterFlect之类的库。

进一步阅读
如果反射效率低下,什么时候最合适?


或者dynamic-显然比反射快一个数量级。
Oded 2012年

1
性能根本不是问题。我只是生动地记得人们在2002年避免了像瘟疫那样的反思。我想知道从那以后发生了什么变化。
blesh 2012年

3
@blesh:没事。人们现在更加熟悉它,而对它却不再那么害怕。
罗伯特·哈维

5
我可能所有人都在这里“下车”,然后说Lisp在OOP 存在之前就已经存在了很久……
Michael K

很公平。我只是想知道是否是过去十年中机器速度的提高才有所不同,还是实际上对System.Reflection进行了更改以提高性能。
blesh 2012年

17

人们警惕不必要使用反射的原因不是性能:是的,使用反射会产生一些开销,但是通常情况下,解决反射问题需要使用具有相当复杂性的另一种方法,即使没有,开销也是很少有意义(尤其是对于应用程序级开发)。

使用反射,人们通常可以对源代码做出的一些重要假设被打破,并且诸如“查找所有引用”之类的工具不再可靠地工作。反射基本上还消除了编译器在C#中强制执行的大多数类型安全,以及类型系统通常会捕获并转化为编译器错误的大多数编程错误,现在最多变为运行时错误,或者变为最模糊的错误。

那么为什么人们要使用反射呢?简而言之,因为尽管存在上述问题,它还是一个非常有价值的工具。通过反思,可以在像C#这样的静态,严格类型化的语言中获得动态编程的一些好处,并且动态编程语言最近已经显示出它们的优点,尤其是在Web编程领域-PHP,Javascript和相当著名的Python ,所有都使用动态类型输入,并被证明非常适合Web编程。但是由于该语言仍然是C#,因此您可以选择将大多数应用程序保留在严格类型的OOP惯用语中,并编写其中动态行为确实对反射有所帮助的一小部分。

一个典型的例子是当您需要将方法公开为Web服务调用时(使用.NET中尚未内置的协议)。严格类型化的OOP方法确实有效,但是它过于严格且笨拙。但是,如果您使用反射将对方法的调用映射而将键/值对映射为参数,则可以为此类Web服务编写一次管道,然后在您喜欢的任何类上使用它。


13

反射仍然比直接调用慢得多。发生了两件事:

  • 运行时具有优化的反射机制,因此差异变得更小
  • CPU变得越来越快,因此较小的低效率更容易容忍

综上所述,这两个因素使反射的成本降低到了您可以常规使用它的程度(在适当的情况下可从可维护性POV中使用),并等待探查器告诉您它是否实际上是瓶颈(并合理地确保大多数时间不会过去)。


4
遗憾的是,CPU的速度变慢了-通常在移动设备和服务器上,人们由于运行它们的成本而试图从服务器中获得尽可能多的效率。
gbjbaanb 2012年

@gbjbaanb:我给您提供移动设备,但是在大多数情况下,在服务器上,购买更多的硬件而不是优化代码是公认的合理选择,因为购买和运行服务器的成本比优化代码的成本。
Michael Borgwardt'4

2
在某些情况下,服务器成本大大超过开发成本。大规模扩展样式。即使服务器功能强大,性能也可能比客户端计算机更为关键。视情况而定。
Tydus勋爵

1
@Lord Tydus:可以,但是您描述的情况很少见。
Michael Borgwardt'4
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.