.NET 反射的“成本”是多少? [复制]

Posted

技术标签:

【中文标题】.NET 反射的“成本”是多少? [复制]【英文标题】:What is the "cost" of .NET reflection? [duplicate] 【发布时间】:2010-09-18 11:06:31 【问题描述】:

可能重复:How costly is .NET reflection?

我目前的编程心态是反射是我最好的朋友。我经常使用它来动态加载允许“松散实现”而不是严格接口的内容,以及许多自定义属性。

使用反射的“实际”成本是多少?

对于频繁反射的类型是否值得努力缓存反射,例如我们自己的 pre-LINQ DAL 对象代码在表定义的所有属性上?

缓存内存占用量会超过反射 CPU 使用率吗?

【问题讨论】:

我到底是怎么在一个 3 个月大并得到回答的话题上投下反对票的? 我们使用通用基类和反射自动化了我们的数据访问层。我们的大多数通用基类都是使用反射实现的。这大大减少了我们必须为重复性任务编写的代码行数。但是性能受到了打击。您采用了哪种解决方案? 我们采用了非常相似的方法,现在正在缓存元数据。 使用fasterflect.codeplex.com的api。对于 getter/setter/invokers 和其他一些东西,它将加快反射速度 500 倍。如果您需要扩展它,也有关于它如何工作的源代码和信息。 很酷,谢谢,会调查的! 【参考方案1】:

反射需要加载大量类型元数据然后进行处理。这可能会导致更大的内存开销和更慢的执行速度。根据this article,属性修改大约慢 2.5x-3x,方法调用慢 3.5x-4x。

这里有一个很好的MSDN article 概述了如何使反射更快以及开销在哪里。如果您想了解更多信息,我强烈建议您阅读。

反射还会增加代码的复杂性,使其更加混乱,因此难以使用。有些人,比如Scott Hanselman 认为,通过使用反射,你经常会遇到比你解决的问题更多的问题。如果您的团队主要是初级开发人员,情况尤其如此。

如果您需要大量动态行为,最好查看 DLR(动态语言运行时)。随着 .NET 4.0 中的新变化,您可能想看看是否可以将其中的一些合并到您的解决方案中。 VB 和 C# 对动态的添加支持使得使用动态代码非常优雅,并且可以相当直接地创建自己的动态对象。

祝你好运。

编辑:我在 Scott 的网站上做了更多的探索,并在反思中发现了这个 podcast。我没听过,但可能值得。

【讨论】:

hanselman.com 的链接不会指向关于反思的文章。 @user1069816,我没有找到 Scott 关于反射成本的特定文章。他在他的播客中顺便提到过几次,并在Hanselminutes 27 - Reflection 中深入探讨了这个话题。【参考方案2】:

权力越大,责任越大。

正如您所说,反射会产生相关成本,并且取决于您进行多少反射,它可能会显着降低应用程序的速度。

其中一个非常适合使用它的地方是 IoC(控制反转),因为根据您的应用程序的大小,它可能会带来更多的好处。

【讨论】:

+1 引用来自蜘蛛侠的彼得叔叔的话【参考方案3】:

感谢伟大的链接和伟大的 cmets,尤其是在 Jr Devs 方面,他们一举两得。

对我们来说,初级开发人员更容易做到这一点:

[TableName("Table")]
public class SomeDal : BaseDal

    [FieldName("Field")]
    public string Field

而不是 DAL 的一些更大的实施。这加快了他们构建 DAL 对象的速度,同时隐藏了所有内部工作,供高级开发人员挖掘。

可惜 LINQ 没有早点出现,我觉得有时我们写了一半。

【讨论】:

显然 NHibernate 相当不错,根据 ALT.NET 的人的说法,所以如果你想要一个替代品,它可能值得一看。我参与的最后一个团队有一个大量使用反射的自定义 ORM 层。只有一个人能够理解它。 我们最终的解决方案是将该层包裹得足够好,这样如果我们在项目后期有时间,就可以移除该层。祝你好运,我能感受到你的痛苦。【参考方案4】:

您可以做很多事情来加速反思。例如,如果您正在进行大量的属性访问,那么HyperDescriptor 可能会很有用。

如果您正在执行大量方法调用,那么您可以使用 Delegate.CreateDelegate 将方法缓存到类型化委托 - 然后只执行一次类型检查等(在 CreateDelegate 期间)。

如果你正在做大量的对象构造,那么Delegate.CreateDelegate 将无济于事(你不能在构造函数上使用它) - 但是(在 3.5 中)Expression 可以用于执行此操作,再次编译到类型化的委托。

所以是的:反射很慢,但你可以优化它而不会太痛苦。

【讨论】:

令人惊讶的是有多少人不知道 Delegate.CreateDelegate,事实上它可能拥有有史以来最好的 MSDN 文档! 链接到 MSDN 以获取 CreateDelegate msdn.microsoft.com/en-us/library/…【参考方案5】:

在使用反射时有时会咬到你的一件事是在进行重构时不使用反射更新调用。当您更改方法名称时,像 resharper 之类的工具会提示您更新 cmets 和字符串,因此您可以通过这种方式捕获其中的大部分,但是当您调用已动态生成的方法或已动态生成的方法名称时,您可能错过了什么。

唯一的解决方案是良好的文档和彻底的单元测试。

【讨论】:

以上是关于.NET 反射的“成本”是多少? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何防止RFID标签被复制 生产商是如何使得RFID标签复制成本变高的 ?

sql server 中何时使用 Money 数据或 Decimal 数据类型来存储成本值? [复制]

在 .net 中分配新数组的大 O 成本

只有两种可能成本的完整图表。从 0 到 N - 1 的最短路径的成本是多少

Golang中切片复制成本,一个大切片会比小切片占用更多内存吗?

Swift 的演员阵容的运行时成本是多少?