C# 反射使用方法 C#如何通过反射获取类型信息

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

如何用
typeof
GetType()
获取类型对象

反射的起点是拿到

Type
实例。最常用两种方式:编译期已知类型用
typeof
,运行时对象用
GetType()
typeof
是编译时运算符,不触发类型初始化;
GetType()
是实例方法,要求对象非 null。

typeof(string)
直接获取
Type
,适用于你知道类型名的场景
"hello".GetType()
返回
System.String
,但若变量为
null
会抛
NullReferenceException
泛型类型需注意:
typeof(List<int>)</int>
正确,
typeof(List)
编译失败(缺少泛型参数)
对于值类型,
GetType()
总是返回装箱后的实际运行时类型,而
typeof
可直接写
typeof(int)

Type.GetMembers()
Type.GetFields()
查看成员结构

拿到

Type
后,常要检查它公开了哪些字段、属性、方法。不同方法返回不同粒度的元数据,且默认只返回 public 成员,需显式传入
BindingFlags
才能访问 private 或静态成员。

type.GetFields()
只返回字段(
FieldInfo
),不含属性;
type.GetProperties()
返回属性(
PropertyInfo
),不含字段
想查私有字段?必须加
BindingFlags.NonPublic | BindingFlags.Instance
,否则返回空数组
type.GetMembers()
是“大杂烩”,返回所有成员(字段、方法、属性、事件等),但不能直接读写值,适合做结构扫描
性能提示:这些方法每次调用都新建数组,频繁调用建议缓存结果,尤其在热路径中

通过
FieldInfo.GetValue()
PropertyInfo.GetValue()
读取值

反射读值的关键是区分“实例成员”和“静态成员”。对实例成员,

GetValue()
第一个参数必须传入对应实例;对静态成员,传
null
即可。

读取实例字段:
fieldInfo.GetValue(obj)
,其中
obj
不能为
null
(除非字段是 static)
读取属性:
propertyInfo.GetValue(obj)
,同样需传实例;若属性有 getter 逻辑,该逻辑会在反射调用时执行
读取静态字段或属性:第二个参数传
null
,如
staticField.GetValue(null)
值类型字段读取后是装箱对象,需手动
Convert.ChangeType()
(int)val
强转——但要注意
null
值和可空类型(
int?
)的处理,否则抛
InvalidCastException

反射调用方法时
MethodInfo.Invoke()
的常见陷阱

Invoke()
看似简单,但参数传递、重载解析、异常包装这三点最容易出错。

参数必须是
object[]
,哪怕方法只有一个
int
参数,也要写成
new object[] { 42 }
;传
int
本身会报错
重载方法必须精确匹配签名,
Invoke()
不会自动转换参数类型(比如传
long
调用
void M(int)
会失败)
被调方法抛出的异常会被包装进
TargetInvocationException
,原始异常在
.InnerException
里,不展开就看不到真实错误
性能极低:比直接调用慢 50–100 倍。如果需要高频调用,考虑用
Delegate.CreateDelegate()
缓存委托,或用
Expression
构建强类型调用器

反射不是黑魔法,它把编译期绑定推迟到运行时,代价是类型安全丢失、调试困难、性能下降。真正要用时,优先确认是否真无法用接口、泛型约束或 Source Generator 替代;一旦选了反射,务必对

null
、装箱、
BindingFlags
组合、异常包装这几个点保持警惕。

相关推荐

热文推荐