C# .NET中IsDefined方法的内部实现逻辑解析
关于
IsDefined方法的实现说明 你在公开参考源码中看到的抛出NotImplementedException的方法,是反射体系公共基类的虚方法占位实现,这个方法的具体逻辑不是由编译器生成实现的,实际逻辑由CLR运行时提供。
为什么公开源码里只看到抛异常的实现?
你看到的这个虚方法定义在ICustomAttributeProvider接口的实现基类,以及MemberInfo、ParameterInfo、Assembly、Module等所有可承载自定义特性的反射类型的公共抽象基类上。这类和运行时元数据深度绑定的逻辑,没有放在托管层的C#源码中实现,而是下沉到了CLR运行时的原生代码层:
- 日常编码拿到的所有反射对象实例(比如
typeof(某类)返回的Type实例、type.GetMethod()返回的MethodInfo实例),实际类型都是CLR运行时内部生成的、继承自对应公开抽象基类的运行时专属子类 - 这些运行时内部子类会重写
IsDefined虚方法,直接调用运行时内部的元数据读取接口完成判断,根本不会执行基类里抛异常的逻辑
重写后的IsDefined方法核心执行逻辑
运行时实现的逻辑可以拆成几个固定步骤:
- 第一步做参数合法性校验:检查传入的
attributeType不为null,且类型确实继承自System.Attribute,校验不通过直接抛出对应参数异常 - 第二步根据
inherit参数决定查找范围:- 若
inherit为false,仅读取当前反射对象自身在程序集元数据CustomAttribute表中的记录,匹配到目标特性类型直接返回true,遍历完无匹配返回false - 若
inherit为true,除了检查当前对象自身的特性,还会沿着继承链向上遍历查找对应父级对象的特性。这里存在一个历史遗留的行为差异:类型、方法、参数的继承查找会走完整继承链,但属性、事件的继承查找不会遍历父类的同名成员,仅检查当前成员
- 若
- 第三步处理特殊伪特性:对于
SerializableAttribute、StructLayoutAttribute这类不存储在CustomAttribute表、直接标记在元数据标志位上的伪自定义特性,运行时会直接读取元数据对应标志位判断,不会走常规特性表查询流程
常见误区澄清
编译器不会为任何用户定义类型生成IsDefined的重写逻辑,这个方法的所有运行时有效实现都是CLR内置的,和用户代码、编译器生成的用户侧代码没有关联。基类里留的抛异常的默认实现,本质是因为不同承载对象(程序集、类型、方法、参数等)的元数据读取路径差异极大,托管基类无法写出统一的通用实现,才把实现下沉到了运行时层。
内容的提问来源于stack exchange,提问作者DEVEL16WINS
相关产品推荐
相关产品推荐

