c# 反射是什么 c#反射性能怎么样

来源:这里教程网 时间:2026-02-21 17:39:03 作者:

C# 反射不是“黑魔法”,而是对程序集元数据的读取和操作能力——它能让你在运行时知道一个类型长什么样、有哪些方法、怎么创建实例,但代价是明确的性能开销。

反射到底在干什么?本质是读元数据,不是反编译

你写的

C#
代码编译后会生成
.dll
.exe
文件,里面除了中间语言(MSIL),还有一块叫「元数据」的二进制区域。它像一张静态说明书,记录了所有类名、方法签名、属性、字段、构造函数、特性(
Attribute
)等信息。

反射(

System.Reflection
)干的事,就是按需打开这张说明书,查表、解析、调用——它不执行反编译,也不还原源码,只读元数据。

✅ 正确理解:反射 = 查类型说明书 + 按说明书动态干活 ❌ 常见误解:“反射能绕过
private
” —— 实际上只能访问
private
成员是因为
BindingFlags.NonPublic
允许你“翻说明书里的隐藏条目”,不是突破访问限制
⚠️ 注意:如果类型没被 JIT 编译过(比如从未实例化),它的元数据依然存在,反射照样能读到

Activator.CreateInstance
MethodInfo.Invoke
是性能重灾区

反射慢,主要慢在这两个环节:它们要走完整的“查找 → 绑定 → 安全检查 → 调用”链路,而直接 new 或方法调用是 JIT 编译后的一条机器指令。

Activator.CreateInstance(typeof(MyClass))
new MyClass()
慢 5–10 倍(无参构造);带参构造更慢,尤其参数类型匹配失败时还会抛异常
methodInfo.Invoke(obj, args)
比直接调用慢 20–100 倍,取决于参数数量和是否需要装箱/拆箱
✅ 性能敏感场景(如高频循环、实时服务)应避免在热路径中使用反射调用 ? 替代方案:缓存
ConstructorInfo
/
MethodInfo
实例;或用
Expression.Lambda
编译成委托(一次编译,多次调用接近原生速度)

什么时候必须用反射?别为了“炫技”硬上

反射不是通用工具,它是为特定解耦场景设计的——当编译时完全不知道类型,又必须在运行时跟它打交道时,才值得引入。

✅ 插件系统:主程序加载
Plugin.dll
,通过约定接口名(如
ICommand
)查找并实例化实现类
✅ ORM 映射:
Dapper
/
EF Core
用反射读取实体类的
PropertyInfo
,把数据库字段映射到对象属性
✅ 序列化框架:
Newtonsoft.Json
用反射遍历属性生成 JSON 字符串
⚠️ 别滥用:比如只是想根据字符串名选一个已知的枚举值,用
Enum.Parse
就够了,不需要
Type.GetType(...).GetMethod(...).Invoke(...)
⚠️ 隐藏风险:反射调用可能因类型版本变化、命名空间变更、强名称校验失败而突然崩溃,且错误堆栈难读

真正该警惕的,不是“反射慢”,而是“反射让调用关系脱离代码可见性”——你改了一个私有字段名,编译器不报错,但某处反射代码就默默挂了。这种隐式依赖,比性能更难维护。

相关推荐