讲师中心 微信公众号
AI工具推荐 视频效率加速

C# 自定义特性方法 C#如何创建和使用Attribute

星辰吖_4140

星辰吖_4140

发布时间:2026-01-22 12:11:02

|

303人浏览过

|

来源于php中文网

原创

自定义Attribute需继承System.Attribute并用AttributeUsage限定目标(如仅方法),类名建议以Attribute结尾;应用时通过反射读取,缺失时返回null而非异常,性能敏感场景应缓存或配合Source Generator在编译期处理。

c# 自定义特性方法 c#如何创建和使用attribute

怎么定义一个可作用于方法的自定义 Attribute

自定义 Attribute 必须继承 System.Attribute,且推荐显式指定 AttributeUsage 来限定它能修饰的目标(比如只允许用在方法上)。不加这个约束,编译器不会报错,但运行时反射读取时可能拿到意外位置的实例。

常见错误是忘记加 [AttributeUsage(AttributeTargets.Method)],结果特性被误标在类或属性上,后续通过 GetCustomAttribute<MyAttr>(method) 查不到——因为根本没允许它出现在方法上。

  • 类名建议以 Attribute 结尾(如 LogExecutionTimeAttribute),C# 允许使用时省略后缀([LogExecutionTime])
  • 构造函数参数决定「位置参数」,public 属性决定「命名参数」
  • 如果需要在 JIT 或 AOT 编译阶段生效(比如影响 IL 生成),普通 Attribute 不行,得用源生成器或 ModuleInitializer 配合

如何在方法上应用并读取自定义 Attribute

应用很简单:[MyCustomAttr("value", Level = 2)];读取必须靠反射,且注意:只有在目标成员被反射访问时,.NET 才会解析并实例化该特性——不是声明时就创建对象。

典型场景是 AOP 式日志、权限校验、序列化控制。但别在热路径里反复调用 GetCustomAttribute,它有反射开销;建议启动时缓存(比如用 ConcurrentDictionary<MethodInfo, T>)。

  • 用 typeof(MyClass).GetMethod("MyMethod").GetCustomAttribute<MyCustomAttr>() 获取单个实例
  • 用 GetCustomAttributes<MyCustomAttr>(true) 的第二个参数为 true 表示查找继承链上的特性
  • 若特性类含复杂初始化逻辑(如打开文件、连接数据库),要格外小心——它会在每次反射获取时执行

为什么 GetCustomAttribute 返回 null 而不是抛异常

GetCustomAttribute<T>() 设计为“查无此特则返回 null”,这是有意为之:绝大多数使用场景下,缺失特性是合法状态(比如某个方法不需要日志,就不打标签),没必要用异常干扰流程。

Skill Weave Chains — 技能链路由引擎
Skill Weave Chains — 技能链路由引擎

开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。

下载

容易踩的坑是直接对返回值调用方法而不判空,导致 NullReferenceException。更隐蔽的问题是:你写了 [MyAttr],但忘了在类/方法上加 public 访问修饰符,导致反射拿不到该成员——此时 GetMethod 返回 null,再调 GetCustomAttribute 就是空引用。

  • 检查目标方法是否为 public,非 public 成员需用 BindingFlags.NonPublic | BindingFlags.Instance
  • 确认程序集已加载,且特性类型未被 Trim(发布时若启用 TrimMode=link,需在 .csproj 中添加 <IsTrimmable>false</IsTrimmable>)
  • 调试时可用 typeof(MyClass).GetMethods().Select(m => (m.Name, m.GetCustomAttribute<MyAttr>())) 快速验证是否被正确识别

Attribute 和 Source Generator 怎么配合避免运行时反射

纯 Attribute 只能在运行时通过反射读取,而 Source Generator 能在编译期扫描这些特性,生成额外代码(比如自动注册 Handler、注入拦截逻辑)。这对性能敏感或 AOT 场景很关键。

比如你写了个 [Route("/api/users")],不用等请求进来再反射找路由,Generator 可直接生成 MapGet 调用。但要注意:Generator 看不到私有成员,也无法处理动态构造的类型名(如字符串拼接的类名)。

  • Generator 必须引用含特性的程序集,且该程序集不能是 InternalsVisibleTo 隐藏的
  • 特性类本身需为 public,且所有构造函数和属性也要是 public,否则 Generator 读不到值
  • 不要在特性中放不可序列化的字段(如委托、Stream),Generator 在编译期无法执行它们

实际项目里最常出问题的,是特性被定义成 internal 却期望在另一个程序集里被反射读到,或者忘了给 AttributeUsage 加 Inherited = true 导致子类方法拿不到父类标记的特性。

热门AI工具

更多
AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1758

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2764

2023.09.04

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

0

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Revel 官方开发手册
Revel 官方开发手册

共0课时 | 0人学习

Buffalo框架路由开发手册
Buffalo框架路由开发手册

共0课时 | 0人学习

Buffalo框架官方文档
Buffalo框架官方文档

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn