当前位置: 首页 > news >正文

深入理解C#特性:从应用到自定义

——解锁元数据标记的高级玩法


💡 核心认知:特性本质揭秘

public sealed class ReviewCommentAttribute : System.Attribute { ... }
  • 特性即特殊类:所有自定义特性必须继承 System.Attribute(基础规则)
  • 命名规范:类名需以 Attribute后缀结尾(如 MyAttributeAttribute
  • 密封建议:强烈推荐声明为 sealed 类(防止意外继承)

⚙️ 特性构造三部曲

1️⃣ 构造函数设计原则

public MyAttributeAttribute(string desc, string ver) 
{Description = desc;  // 位置参数 VersionNumber = ver;
}
  • 强制公有构造:至少需一个公共构造函数(隐式无参构造也可用)
  • 参数限制:仅接受编译期常量(常量表达式)

2️⃣ 应用时的构造规则

[MyAttribute("Holds a value")]          // 单参数构造
[MyAttribute("V1.3", Reviewer="Alice")] // 位置参数+命名参数
  • 位置参数优先:对应构造函数参数顺序
  • 命名参数扩展:初始化公共字段/属性(需在位置参数后)

3️⃣ 无参构造的简写

[MyAttr]   // 等效于 [MyAttr()]
class MyClass 

🔐 精准控制特性作用域(AttributeUsage)

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, // 目标类型 Inherited = false,     // 禁止继承 AllowMultiple = false  // 禁止重复应用
)]
public sealed class AuditAttribute : Attribute { ... }
参数作用默认值
ValidOn指定目标类型(枚举按位组合)必填
Inherited是否被派生类继承true
AllowMultiple同一目标是否允许多次应用false

常用目标类型(AttributeTargets枚举):

  • Class | Method | Property
  • Field | Constructor | Assembly

✅ 自定义特性最佳实践

1. 职责单一

特性类应仅描述目标结构的元数据状态(如版本/作者/描述)

2. 安全封装

// ✅ 正确示范 
public string Version { get; } // 只读属性// ❌ 避免 
public void Validate() { ... } // 禁止添加方法

3. 参数设计规范

  • 必需参数 → 通过构造函数位置参数传递
  • 可选参数 → 通过公共字段/属性+命名参数设置

4. 完整声明示例

[AttributeUsage(AttributeTargets.Class)]
public sealed class ApiVersionAttribute : Attribute
{public string Version { get; }public string Author { get; set; }  // 可选命名参数public ApiVersionAttribute(string version) => Version = version;
}// 应用示例 
[ApiVersion("2.1.0", Author = "Jane")]
public class PaymentService { ... }

💎 关键要点回顾

概念要点说明
特性本质继承System.Attribute的特殊类
构造函数支持重载,参数需为编译期常量
参数传递位置参数必填在前,命名参数补充在后
作用域控制AttributeUsage精确限制目标类型
安全实践密封类 + 只包含字段/属性 + 显式目标声明

特性如代码的“智能标签”
它不改变逻辑,却为程序注入结构化元数据。掌握自定义特性,等于拥有为代码打上语义化标记的能力,让架构意图更清晰,让扩展更优雅。


📚 进阶提示:特性需通过反射读取(如GetCustomAttributes()),后续可探索特性与AOP编程、编译时分析的深度结合!

http://www.lryc.cn/news/624037.html

相关文章:

  • 一起Oracle 19c bug 导致的业务系统超时问题分析
  • 嵌入式C语言学习笔记之枚举、联合体
  • Jenkins - CICD 注入环境变量避免明文密码暴露
  • 图解直接插入排序C语言实现
  • 跨越南北的养老对话:为培养“银发中国”人才注入新动能
  • 数据准备|生成折线图
  • Python自学09-常用数据结构之元组
  • Java语法进阶之常用类
  • 【新手入门】Android基础知识(二):Binder进程间通信,理解Binder工作原理以及Binder实体、Binder引用、Binder代理概念
  • K8S集群环境搭建(一)
  • 双指针和codetop2(最短路问题BFS)
  • Maven依赖范围
  • 检查xrdp远程连接桌面卡顿的问题(附解决sh脚本)
  • STM32入门之USART串口部分
  • # C++ 中的 `string_view` 和 `span`:现代安全视图指南
  • 多墨智能-AI一键生成工作文档/流程图/思维导图
  • Transformer 面试题及详细答案120道(61-70)-- 解码与生成
  • Spring IOC 学习笔记
  • Spring 创建 Bean 的 8 种主要方式
  • Vue3 中的 ref、模板引用和 defineExpose 详解
  • 数据结构初阶(18)快速排序·深入优化探讨
  • 【深度学习-基础知识】单机多卡和多机多卡训练
  • oom 文件怎么导到visualvm分析家
  • 生成模型实战 | InfoGAN详解与实现
  • 停车位 车辆
  • AI出题人给出的Java后端面经(十七)(日更)
  • 【URP】[法线贴图]为什么主要是蓝色的?
  • YoloV9改进策略:Block改进-DCAFE,并行双坐标注意力机制,增强长程依赖与抗噪性-即插即用
  • LangChain4j
  • Java 学习笔记(基础篇4)