当前位置: 首页 > 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.dtcms.com/a/335684.html

相关文章:

  • CentOS启动两个MySQL实例
  • C#对象的本地保存与序列化详解笔记
  • [每周一更]-(第155期):Go 1.25 发布:新特性、技术思考与 Go vs Rust 竞争格局分析
  • 【前端面试题】前端面试知识点(第三十一题到第六十一题)
  • 项目发布上线清单
  • neo4j导入导出方法
  • 《设计模式》抽象工厂模式
  • 链表OJ题讲解---试金石含金量
  • RabbitMQ入门:生产者和消费者示例
  • Java注解学习记录
  • 什么是EDA(Exploratory Data Analysis,探索性数据分析)
  • AI出题人给出的Java后端面经(十七)(日更)
  • 第 463 场周赛(GPT-3,Me-1)
  • Foreign-Memory Access API外部内存API
  • 混沌工程(Chaos engineering):系统韧性保障之道
  • 计算机网络 HTTPS 全流程
  • p5.js 3D 形状 “预制工厂“——buildGeometry ()
  • 【位运算】查询子数组最大异或值|2693
  • 图灵完备(Turing Complete)免安装中文版
  • 关于pygsp引发的一系列问题和实例小demo
  • ​​Vue 3 开发速成手册
  • 裸机框架:按键模组
  • macos 安装nodepad++ (教程+安装包+报错后的解决方法)
  • AI证书怎么选
  • 交叉编译 手动安装 SQLite 库 移植ARM
  • 基于Vue + Node能源采购系统的设计与实现/基于express的能源管理系统#node.js
  • JavaScript 性能优化实战大纲
  • 记SpringBoot3.x + Thymeleaf 项目实现(MVC架构模式)
  • .NET 中的延迟初始化:Lazy<T> 与LazyInitializer
  • 【Java后端】MyBatis-Plus 原理解析