深入理解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.pswp.cn/pingmian/93400.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习-集成学习(EnsembleLearning)

0 结果展示 0.1 鸢尾花分类 import pandas as pd import numpy as npfrom sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, recall_score, f1_score, classification_repo…

Golang database/sql 包深度解析(一)

database/sql 是 Go 语言标准库中用于与 SQL(或类 SQL)数据库交互的核心包,提供了一套轻量级、通用的接口,使得开发者可以用统一的方式操作各种不同的数据库,而无需关心底层数据库驱动的具体实现。 核心设计理念 datab…

文章自然润色 API 数据接口

文章自然润色 API 数据接口 ai / 文本处理 基于 AI 的文章润色 专有模型 / 智能纠错。 1. 产品功能 基于自有专业模型进行 AI 智能润色对原始内容进行智能纠错高效的文本润色性能全接口支持 HTTPS(TLS v1.0 / v1.1 / v1.2 / v1.3);全面兼容…

【状压DP】3276. 选择矩阵中单元格的最大得分|2403

本文涉及知识点 C动态规划 3276. 选择矩阵中单元格的最大得分 给你一个由正整数构成的二维矩阵 grid。 你需要从矩阵中选择 一个或多个 单元格,选中的单元格应满足以下条件: 所选单元格中的任意两个单元格都不会处于矩阵的 同一行。 所选单元格的值 互…

IDEA 清除 ctrl+shift+r 全局搜索记录

定位文件:在Windows系统中,文件通常位于C:Users/用户名/AppData/Roaming/JetBrains/IntelliJIdea(idea版本)/workspace目录下,文件名为一小串随机字符;在Mac系统中,文件位于/Users/用户名/Library/Application /Suppor…

解锁AI大模型:Prompt工程全面解析

解锁AI大模型&#xff1a;Prompt工程全面解析 本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型开发 学习视频/籽料/面试题 都在这>>Github<< 从新手到高手&#xff0c;Prompt 工程究竟是什么&#xff1f; 在当今数字化时代&#xff0c;AI …

HTTP0.9/1.0/1.1/2.0

在HTTP0.9中&#xff0c;只有GET方法&#xff0c;没有请求头headers&#xff0c;没有状态码&#xff0c;只能用于传输HTML文件。到了HTTP1.0(1996)&#xff0c;HTTP1.0传输请求头&#xff0c;有状态码&#xff0c;并且新增了POST和HEAD方法。HTTP1.0中&#xff0c;使用短连接&a…

gitee 流水线+docker-compose部署 nodejs服务+mysql+redis

文章中的方法是自己琢磨出来的&#xff0c;或许有更优解&#xff0c;共同学习&#xff0c;共同进步&#xff01; docker-compose.yml 文件配置&#xff1a; 说明&#xff1a;【配置中有个别字段冗余&#xff0c;但不影响使用】该文件推荐放在nodejs项目的根目录中&#xff0c…

【算法】模拟专题

什么是模拟&#xff1f; 是一种通过模仿现实世界或问题场景的运行过程来求解问题的算法思想。它不依赖复杂的数学推导或逻辑优化&#xff0c;而是按照问题的实际规则、步骤或流程&#xff0c;一步步地 “复现” 过程&#xff0c;最终得到结果。 使用场景&#xff1a;当问题的逻…

【FreeRTOS】刨根问底6: 应该如何防止任务栈溢出?

【加关注&#xff0c;不迷路】一、栈溢出&#xff1a;程序世界的“越界洪水”就象一个装水的玻璃杯&#xff08;栈空间&#xff09;&#xff0c;每次调用函数就像向水杯中倒水&#xff08;压入保护需要恢复的数据&#xff09;。当函数嵌套调用过深&#xff08;如递归失控&#…

牛客周赛 Round 105

A.小苯的xor构造题目描述小红喜欢整数 k&#xff0c;他想让小苯构造两个不相等的非负整数&#xff0c;使得两数的异或和等于 k。请你帮帮小苯。#include <bits/stdc.h> using namespace std; using ll long long; void solve() {int k;cin>>k;cout<<0<&l…

《R for Data Science (2e)》免费中文翻译 (第4章) --- Workflow: code style

写在前面 本系列推文为《R for Data Science (2)》的中文翻译版本。所有内容都通过开源免费的方式上传至Github&#xff0c;欢迎大家参与贡献&#xff0c;详细信息见&#xff1a; Books-zh-cn 项目介绍&#xff1a; Books-zh-cn&#xff1a;开源免费的中文书籍社区 r4ds-zh-cn …

11-verilog的RTC驱动代码

verilog的RTC驱动代码 1.例化parameter SLAVE_ADDR 7h51 ; // 器件地址 parameter BIT_CTRL 1b0 ; // 字地址位控制参数(16b/8b) parameter CLK_FREQ 26d50_000_000; // i2c_dri模块的驱动时钟频率(CLK_FREQ) parameter I2C_FR…

【k8s、docker】Headless Service(无头服务)

文章目录问题背景1、什么是Headless Service1.2 为什么 Zookeeper 使用 Headless Service&#xff1f;1.2 Headless Service 的 DNS 行为1.3 验证示例1.4 如何创建 Headless Service&#xff1f;2. zk-0.zookeeper.default.svc.cluster.local 域名是如何创建出来的&#xff1f;…

scikit-learn/sklearn学习|套索回归Lasso解读

【1】引言 前序学习进程中&#xff0c;对用scikit-learn表达线性回归进行了初步解读。 线性回归能够将因变量yyy表达成由自变量xxx、线性系数矩阵www和截距bbb组成的线性函数式&#xff1a; y∑i1nwi⋅xibwTxby\sum_{i1}^{n}w_{i}\cdot x_{i}bw^T{x}byi1∑n​wi​⋅xi​bwTxb实…

暴雨服务器:以定制化满足算力需求多样化

在数字经济与实体经济深度融合的浪潮下&#xff0c;互联网行业正经历着前所未有的技术变革。大数据分析、云计算服务、人工智能算法等技术的快速演进&#xff0c;推动着企业对于高性能计算基础设施的需求呈现指数级增长。据IDC数据显示&#xff0c;互联网行业已成为全球服务器采…

JavaScript字符串详解

创建字符串&#xff1a; 1.使用字面量(推荐)&#xff1a; 这是最常用、最直接的方式。你可以用单引号 ()、双引号 (") 或反引号 () 把文本包起来 let singleQuote 单引号; let doubleQuote "双引号"; let templateLiteral 反引号;2.使用String 构造函数&…

Kiro Preview 应用评测

Kiro应用评测 Kiro 是一个由亚马逊推出的 AI 驱动的智能开发环境&#xff0c;从原型到生产全程陪伴您的开发过程。它将"灵感编程"的流畅性与规范的清晰性相结合&#xff0c;帮助您更快地构建更好的软件。 昨天收到了Kiro的试用邮件&#xff0c;收到邮件后第一时间下载…

Flink2.0学习笔记:Flink服务器搭建与flink作业提交

一&#xff0c;下载flink:Downloads | Apache Flink,解压后放入IDE工作目录&#xff1a;我这里以1.17版本为例 可以看到&#xff0c;flink后期的版本中没有提供window启动脚本:start-cluster.bat 所以这里要通过windows自带的wsl 系统启动它 打开终端依次运行下列命令完成w…

MySQL锁的分类

MySQL锁可以按照多个维度进行分类&#xff0c;下面我用最清晰的方式为你梳理所有分类方式&#xff1a;一、按锁的粒度分类&#xff08;最常用分类&#xff09;锁类型作用范围特点适用引擎示例场景表级锁整张表开销小、加锁快&#xff0c;并发度低MyISAM, MEMORY数据迁移、全表统…