You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用PropertyInfo.GetValue获取Nullable<T>属性返回实际值的原因

核心原因

这个现象本质是CLR对Nullable<T>的专属装箱规则导致的,和PropertyInfo.GetValue本身的实现没有直接关系。
PropertyInfo.GetValue的返回值类型是object,所有值类型在返回前都会经历装箱过程转换为引用类型。而CLR对Nullable<T>的装箱逻辑做了硬编码的特殊处理:

  • 当Nullable<T>实例的HasValue为false时,装箱结果直接是null引用
  • 当Nullable<T>实例的HasValue为true时,装箱时不会把整个Nullable<T>结构体打包,而是直接提取内部存储的Value字段的值,对这个T类型的值做装箱返回

也就是说运行时层面根本不存在装箱后的Nullable<T>对象,你自然不可能通过返回object的方法拿到这种实例。你可以用非常简单的代码验证这个规则,完全不需要用到反射:

int? testValue = 100;
object boxedResult = testValue;
// 输出结果是System.Int32,而非Nullable<Int32>
Console.WriteLine(boxedResult.GetType());

int? nullValue = null;
object boxedNull = nullValue;
// 输出True,装箱结果直接是空引用
Console.WriteLine(boxedNull == null);

反射调用GetValue只是刚好触发了这个装箱流程而已,不是反射单独给Nullable做了特殊判断。

是不是.NET内置的专属机制

是,这个逻辑是写在CLR核心层面的硬编码规则,仅对System.Nullable<T>这一个泛型类型生效,没有任何公开的扩展入口。
你自己定义的结构体哪怕完全复刻Nullable<T>的结构,包含HasValue属性和对应的值字段,装箱时也会走普通值类型的装箱逻辑,把整个结构体实例打包到托管堆上,不会出现自动拆出内部值的行为。

自定义类型能否实现相同效果

不能。
这种装箱层面的行为是运行时内置的,既不支持通过特性、接口实现,也不支持自定义类型注册类似的转换逻辑。如果你只是想在自己的业务反射逻辑里达到类似的效果,只能手动写一层包装判断:当识别到目标类型是你自定义的包装类型时,主动提取其内部封装的实际值返回,但这属于上层业务逻辑的自定义处理,和CLR原生的Nullable特殊机制完全不是一个层面的实现。

内容的提问来源于stack exchange,提问作者Krisztián Szilágyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:36:21