C# 反射太慢?这几种方案让你性能翻倍

26 阅读4分钟

前言

C#的反射确实慢,可以通过优化来缓解。

反射是 C#语言中一种非常有用的机制,它可以在运行时动态获取对象的类型信息并且进行相应的操作。

反射能干什么?

使用反射可以让我们在运行时动态地获取对象的类型信息并进行相应的操作,比如创建对象、调用方法、获取属性等。

举个简单的例子,我们在写代码时,为了能够调用某个对象的方法,我们通常需要先创建这个对象的实例,然后才能调用其方法。而使用反射机制,我们可以在运行时动态地创建对象并直接调用其方法,而不必提前定义它们。

虽然反射提供了强大的动态编程能力,但是其性能的开销也不容忽视,我们所说的慢其实就源自这里。

一、反射性能分析

其实经过测试发现,C# 反射比直接调用要慢几百倍,不过经过优化后性能是可以大幅提升的。

反射的性能主要受到 5 个因素的制约,包括:类型加载、元数据解析、动态调用、安全检查以及缓存机制。

二、反射与直接调用性能对比

在我的 win11 系统中,使用基于.Net 的基准测试工具 BenchmarkDotNet,对每个场景进行了大量测试。

1、属性访问测试,实际是方法调用的封装

2、方法调用测试,主要是参数处理和动态调用

3、构造函数测试,需要参数类型匹配和对象是实例化等。

4、字段访问测试

三、反射的底层执行流程

反射的执行分为 6 个步骤:类型查找、元数据解析、安全检查、参数处理、动态调用、最终进行结果处理返回值。

那为什么直接调用比反射快呢?

直接调用在编译时就确切调用了目标,运行时直接执行,而反射要到运行时才能确定,而且还要进行大量的查找、解析、验证等工作,所以就慢了。

四、反射性能的优化策略

策略 1:缓存 Type 对象,简单有效

策略 2:委托代替反射(我推荐的方案)

策略 3:表达式树编译(这个方法比较高级)

策略 4:IL 动态生成(性能好)

这个比较复杂,但性能提升显著,接近原生调用了。感兴趣的同学可以查资料仔细研究一下。

五、反射性能优化案例

1、那什么时候适合用反射呢?

在框架开发(比如 ORM、IoC 容器、序列化框架)、动态绑定配置对象、动态加载和调用插件、元数据生成代码等场景比较适合使用反射。

2、什么时候不适合反射呢?

频繁执行的业务逻辑、对性能敏感的业务、以及一些简单操作(能用泛型和接口解决的问题)不推荐用反射。

总结

最后,反射确实很慢,不仅 C# 里的反射,其他语言的反射也有类似的问题,不过可以通过合理的设计和优化,来缓解慢的问题。

这个问题其实就是在性能、灵活性和复杂度之间的平衡问题,你说呢?

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!