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

哪些条件下获取同一属性的PropertyInfo会是不同实例而非缓存值?

何时代表同一属性的两个PropertyInfo引用会不是同一实例?

通常两次获取某类属性的PropertyInfo时会返回同一实例:

var propertyOne = typeof(Foo).GetProperty(nameof(Foo.Bar));
var propertyTwo = typeof(Foo).GetProperty(nameof(Foo.Bar));
Console.WriteLine(propertyOne == propertyTwo); // 输出 "True"

这是因为.NET内部会缓存PropertyInfo实例,第二次调用GetProperty(...)时直接返回缓存的实例,但这种引用相等并非绝对保证。

我曾在VS调试时遇到过特殊场景:代表同一具体类同一属性的两个PropertyInfo实例,调用Equals(...)结果不相等。检查后发现它们的属性名、类型、反射相关属性等都完全一致,但确实是不同实例——其中一个实例是从LambdaExpression的主体获取的。之后我无法复现该问题,无论用何种方式获取都得到同一实例,也没有相关日志记录。我打算不再依赖引用相等比较,但好奇这种情况的发生条件及复现方法。


会返回不同PropertyInfo实例的场景

  • 动态生成类型的属性:使用Reflection.Emit或其他动态代码生成技术创建的类型,即使属性定义和原类型完全一致,其PropertyInfo实例也会和原类型对应属性的实例不同。多次生成结构相同的动态类型,各自的PropertyInfo实例也互不相同。
  • 跨应用程序域获取:在.NET Framework中,不同AppDomain的类型是隔离的。同一程序集里的同一类,在不同AppDomain中获取的PropertyInfo是不同引用——每个AppDomain都有独立的类型缓存和反射对象实例。
  • Lambda表达式解析的特殊情况:你遇到的LambdaExpression场景可能和表达式树的构造或编译逻辑有关。比如动态构建的表达式树(而非直接从编译后代码提取),在某些.NET版本或优化逻辑下可能生成新的PropertyInfo实例。这种场景很难稳定复现,具体取决于表达式树的构建方式和运行时环境。
  • 程序集重复加载:同一程序集通过不同加载上下文多次加载到同一AppDomain(比如用Assembly.LoadFrom加载本地文件,同时该程序集也在GAC中),此时同一类的类型实例本身就是不同的,对应的PropertyInfo自然也不是同一引用。
  • 特殊绑定标志组合:虽然少见,但如果两次获取属性时使用了差异较大的BindingFlags组合(比如一次仅指定BindingFlags.Public,另一次同时指定BindingFlags.Public | BindingFlags.DeclaredOnly),在某些边缘场景下可能返回不同的PropertyInfo实例。不过大多数情况下,只要指向同一属性,即使绑定标志不同,.NET仍会返回缓存实例。

最佳实践

永远不要依赖PropertyInfo的引用相等判断是否指向同一属性,正确的做法是:

  • 使用PropertyInfo.Equals()方法(该方法会验证属性所属类型及成员标识是否一致)
  • 或者组合比较PropertyInfo.MetadataToken和DeclaringType,确保成员和所属类型都匹配

内容的提问来源于stack exchange,提问作者Ergwun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:15:33