14 KiB
.NET 注释规范
参考来源:Microsoft C# XML 文档注释 · 推荐的文档注释标签 · 框架设计准则
核心原则:公共 API 必须注释、说明意图而非复述代码、保持与代码同步
一、概述
C# 使用 XML 文档注释为代码提供结构化文档。编译器从 ///(三斜杠)注释中生成 XML 文件,供 IDE 智能提示和文档生成工具使用。
二、XML 注释标签
2.1 核心标签
| 标签 | 用途 | 适用场景 |
|---|---|---|
<summary> |
简要描述类型或成员的功能 | 所有公共类型和成员 |
<param> |
描述方法参数 | 方法、构造函数 |
<returns> |
描述方法返回值 | 有返回值的方法 |
<remarks> |
补充说明,提供额外细节 | 需要详细解释的成员 |
<value> |
描述属性所代表的值 | 属性 |
2.2 引用标签
| 标签 | 用途 | 示例 |
|---|---|---|
<see cref=""/> |
行内引用其他类型或成员 | <see cref="MyClass"/> |
<seealso cref=""/> |
在"另请参阅"区域添加引用 | <seealso cref="OtherMethod"/> |
<paramref name=""/> |
引用参数名 | <paramref name="count"/> |
<typeparamref name=""/> |
引用泛型类型参数名 | <typeparamref name="T"/> |
2.3 格式标签
| 标签 | 用途 |
|---|---|
<para> |
在 <remarks> 等标签内分段 |
<list> |
创建列表或表格 |
<code> |
多行代码示例 |
<example> |
包含使用示例 |
2.4 泛型与继承标签
| 标签 | 用途 |
|---|---|
<typeparam> |
描述泛型类型参数 |
<inheritdoc/> |
继承基类或接口的文档注释 |
三、注释范围要求
3.1 必须添加注释的成员
| 访问级别 | 要求 |
|---|---|
public |
必须添加完整 XML 注释 |
protected |
必须添加完整 XML 注释 |
internal |
建议添加 XML 注释 |
private |
仅在逻辑复杂时添加 |
3.2 各成员类型的注释要求
| 成员类型 | 必需标签 | 可选标签 |
|---|---|---|
| 类 / 结构 | <summary> |
<remarks>、<typeparam> |
| 接口 | <summary> |
<remarks> |
| 方法 | <summary>、<param>、<returns> |
<remarks>、<example> |
| 构造函数 | <summary>、<param> |
— |
| 属性 | <summary> |
<value> |
| 事件 | <summary> |
<remarks> |
| 枚举类型 | <summary> |
— |
| 枚举值 | <summary> |
— |
| 委托 | <summary>、<param>、<returns> |
— |
| 接口实现成员 | <inheritdoc/> |
— |
| override 方法 | 不添加注释 | — |
四、书写原则
4.1 <summary> 书写规范
✔️ 一句话说明"做什么",而非"怎么做"。
✔️ 以第三人称动词开头。
✔️ 句号规则:注释内容含逗号、分号等分句标点时,末尾加句号;纯短语不加句号。
// ✔️ 含逗号 → 加句号
/// <param name="timeout">超时时间(秒),0 表示不限制。</param>
/// <returns>下载结果,包含状态码和错误信息。</returns>
// ✔️ 纯短语 → 不加句号
/// <param name="url">资源包的完整下载地址</param>
/// <returns>初始化操作句柄</returns>
❌ 禁止重复方法名或参数类型中已表达的信息。
❌ 禁止在注释中重复方法命名后缀已表达的语义。常见后缀包括:
| 命名后缀 | 已表达的语义 | 注释中禁止使用 |
|---|---|---|
Async |
异步执行 | "异步" |
Internal |
内部实现 | "内部" |
❌ 禁止以"这个方法"、"该类"等冗余前缀开头。
4.2 常见开头约定
属性 —— 描述值本身,不加动词前缀
属性的 { get; } / { get; set; } 访问器已表达读写语义,summary 应直接描述值的含义,避免用"获取"、"获取或设置"等动词前缀重复已知信息。
| 属性类型 | 推荐写法 | 反例 |
|---|---|---|
| 只读属性 | 名词短语,如 "错误信息" | |
| 可读写属性 | 名词短语,如 "当前下载进度" | |
| 返回 bool 的属性 | "是否……",如 "是否为只读缓存" |
方法 —— 以动词开头
| 成员类型 | 推荐开头动词 |
|---|---|
| 返回 bool 的方法 | "检查是否"、"判断是否" |
| 获取类方法 | "获取"、"查询" |
| 设置类方法 | "设置"、"更新" |
| 创建类方法 | "创建"、"构建"、"生成" |
| 事件 | "当……时触发" |
| 构造函数 | "创建 XXX 实例"(XXX 为类型的中文描述) |
4.3 <param> 书写规范
✔️ 描述参数的含义和用途。
✔️ 说明有效范围和边界值(如为 null 时的行为、取值范围)。
❌ 禁止仅重复参数名或类型名,如"url 参数"。
4.4 <returns> 书写规范
✔️ 说明返回值的含义。
✔️ 说明特殊返回值的含义(如返回 null 表示未找到)。
4.5 <remarks> 书写规范
✔️ 多行内容必须用 <para> 包裹每段,否则 IDE 会将多行合并显示为一行。
// ✔️ 好:每段用 <para> 包裹
/// <remarks>
/// <para>下载并加载 Unity AssetBundle 资源包</para>
/// <para>支持 Unity 内置缓存机制和 CRC 校验</para>
/// </remarks>
// ❌ 差:多行纯文本,IDE 显示时会合并为一行
/// <remarks>
/// 下载并加载 Unity AssetBundle 资源包
/// 支持 Unity 内置缓存机制和 CRC 校验
/// </remarks>
✔️ 单行内容可直接书写,无需 <para>。
五、注释示例
5.1 类注释
/// <summary>
/// 资源包下载请求,负责管理单个资源包的下载生命周期。
/// </summary>
/// <remarks>
/// <para>支持断点续传和失败重试</para>
/// <para>通过 <see cref="DownloadRetryController"/> 控制重试策略</para>
/// </remarks>
public class BundleDownloadRequest
{
}
5.2 方法注释
/// <summary>
/// 从指定 URL 下载资源包并保存到本地磁盘
/// </summary>
/// <param name="url">资源包的完整下载地址</param>
/// <param name="savePath">本地保存的目标路径</param>
/// <param name="timeout">超时时间(秒),0 表示不限制。</param>
/// <returns>下载结果,包含状态码和错误信息。</returns>
public async Task<DownloadResult> DownloadAsync(string url, string savePath, int timeout = 30)
{
}
5.3 属性注释
/// <summary>
/// 当前下载进度
/// </summary>
/// <value>取值范围 0.0 ~ 1.0,其中 1.0 表示下载完成。</value>
public float Progress { get; private set; }
5.4 枚举注释
/// <summary>
/// 下载任务的运行状态
/// </summary>
public enum DownloadStatus
{
/// <summary>
/// 等待中,尚未开始下载。
/// </summary>
Pending,
/// <summary>
/// 正在下载中
/// </summary>
Downloading,
/// <summary>
/// 下载已完成
/// </summary>
Completed,
/// <summary>
/// 下载失败
/// </summary>
Failed
}
5.5 泛型类注释
/// <summary>
/// 通用对象池,提供对象的复用管理。
/// </summary>
/// <typeparam name="T">池化对象的类型,必须实现 <see cref="IDisposable"/>。</typeparam>
public class ObjectPool<T> where T : IDisposable
{
}
5.6 接口注释
/// <summary>
/// 定义下载请求的标准行为
/// </summary>
public interface IDownloadRequest
{
/// <summary>
/// 请求的远程 URL
/// </summary>
string URL { get; }
/// <summary>
/// 取消当前下载请求
/// </summary>
void Abort();
}
5.7 使用 <inheritdoc/>
接口实现 —— 使用 <inheritdoc/>
实现接口成员时,使用 <inheritdoc/> 继承接口中定义的文档:
public class MyDownloadRequest : IDownloadRequest
{
/// <inheritdoc/>
public string URL { get; }
/// <inheritdoc/>
public void Abort()
{
}
}
基类继承(override) —— 不添加任何注释
重写基类方法时,不需要添加任何 XML 文档注释(包括 <inheritdoc/>)。方法签名中的 override 关键字已明确表达继承关系,IDE 会自动展示基类文档。
// ✔️ 好:override 方法不添加注释
protected override void InternalStart()
{
}
protected override void InternalUpdate()
{
}
// ❌ 差:多余的 inheritdoc
/// <inheritdoc/>
protected override void InternalStart()
{
}
5.8 使用 <example> 和 <code>
/// <summary>
/// 根据资源路径加载资源对象
/// </summary>
/// <param name="assetPath">资源路径</param>
/// <returns>资源操作句柄,加载失败时资源对象为 null。</returns>
/// <example>
/// 加载一个预制体:
/// <code>
/// var handle = package.LoadAssetAsync<GameObject>("Assets/Prefabs/Player.prefab");
/// await handle.Task;
/// var prefab = handle.AssetObject as GameObject;
/// </code>
/// </example>
public AssetHandle LoadAssetAsync<T>(string assetPath)
{
}
六、反面示例
6.1 冗余注释
// ❌ 差:重复方法签名中已有的信息
/// <summary>
/// 下载方法,参数是 url 和 savePath。
/// </summary>
public void Download(string url, string savePath) { }
// ✔️ 好:说明行为和目的
/// <summary>
/// 从远程服务器下载资源包并保存到本地磁盘
/// </summary>
/// <param name="url">资源包的完整下载地址</param>
/// <param name="savePath">本地保存的目标路径</param>
public void Download(string url, string savePath) { }
6.2 废话参数注释
// ❌ 差:仅重复参数名
/// <param name="name">名称</param>
// ✔️ 好:说明含义和约束
/// <param name="name">资源包的唯一标识名称</param>
6.3 重复命名后缀
// ❌ 差:方法名 Async 后缀已表达异步语义
/// <summary>
/// 异步加载资源对象
/// </summary>
public AssetHandle LoadAssetAsync(string location) { }
// ✔️ 好:描述功能意图,不重复后缀语义
/// <summary>
/// 加载资源对象
/// </summary>
public AssetHandle LoadAssetAsync(string location) { }
6.4 缺少边界说明
// ❌ 差:未说明返回 null 的情况
/// <returns>资源对象</returns>
// ✔️ 好:说明特殊返回值
/// <returns>加载到的资源对象</returns>
七、行内注释规范
对于非 XML 文档注释(// 普通注释),遵循以下原则:
7.1 基本准则
✔️ 解释"为什么",而非"是什么"——代码本身应说明"做什么",注释解释不明显的意图或约束。
✔️ 标记待办事项使用 // TODO: 前缀。
✔️ 标记临时方案使用 // HACK: 前缀。
✔️ 修改代码时同步更新相关注释,过时的注释比没有注释更有害。
❌ 禁止注释显而易见的代码,如 // 递增计数器、// 返回结果。
❌ 禁止用注释替代清晰的命名——如果需要注释来解释变量含义,应优先改善变量名。
7.2 示例
// ❌ 差:复述代码
// 如果计数大于最大值,重置为零
if (count > maxCount)
count = 0;
// ✔️ 好:解释约束
// 环形缓冲区写满后从头覆盖,避免无限增长
if (count > maxCount)
count = 0;
八、术语翻译映射表
为保持注释用语统一,以下列出项目中常用英文类型/概念与其中文翻译的对应关系。 撰写或审核注释时,请以此表为准。
8.1 核心领域类型
| 英文类型 / 概念 | 中文翻译 | 备注 |
|---|---|---|
PackageBundle |
资源包描述 | 清单中的静态元数据(Package* = 描述) |
PackageAsset |
资源描述 | 清单中的静态元数据(Package* = 描述) |
AssetInfo |
资源信息 | 运行时上下文(*Info = 信息) |
BundleInfo |
资源包信息 | 运行时上下文(*Info = 信息) |
ResourcePackage |
资源包裹 | 顶层包裹容器 |
PackageManifest |
包裹清单 / 资源清单 | — |
AssetBundle |
AssetBundle | Unity 引擎类型,保留英文 |
RawBundle |
原生资源包 | 非 AssetBundle 的原始文件 |
8.2 文件系统与缓存
| 英文类型 / 概念 | 中文翻译 | 备注 |
|---|---|---|
IFileSystem |
文件系统 | — |
IBundleCache |
缓存系统 | — |
ICacheEntry |
缓存条目 | — |
BundleGuid |
资源包 GUID / Bundle 唯一标识 | — |
ICacheEvictionPolicy |
淘汰策略 | — |
EvictionResult |
淘汰结果 | — |
8.3 下载与网络
| 英文类型 / 概念 | 中文翻译 | 备注 |
|---|---|---|
IDownloadRequest |
下载请求 | — |
IDownloadBackend |
下载后台 | — |
IRemoteService |
远端资源服务 | — |
IDownloadRetryPolicy |
下载重试策略 | — |
IDownloadUrlPolicy |
URL 选择策略 | — |
8.4 加密与解密
| 英文类型 / 概念 | 中文翻译 | 备注 |
|---|---|---|
IBundleEncryptor |
资源包加密器 | — |
IBundleDecryptor |
资源包解密器 | 基接口,需实现派生接口 |
IManifestEncryptor |
资源清单加密器 | — |
IManifestDecryptor |
资源清单解密器 | — |
BundleEncryptArgs |
加密操作的输入参数 | — |
BundleDecryptArgs |
解密操作的输入参数 | — |
8.5 资源加载与句柄
| 英文类型 / 概念 | 中文翻译 | 备注 |
|---|---|---|
IBundleHandle |
资源包句柄 | — |
AssetHandle |
资源句柄 | — |
RawFileHandle |
原生文件句柄 | — |
SubAssetsHandle |
子资源句柄 | — |
8.6 通用术语
| 英文术语 | 中文翻译 | 备注 |
|---|---|---|
| Package | 包裹 | 项目级容器 |
| Bundle | 资源包 | 构建产物单元 |
| Asset | 资源 | 单个资源文件 |
| Manifest | 清单 | — |
| Handle | 句柄 | — |
| Operation | 操作 / 异步操作 | — |
| Scheduler | 调度器 | — |
| Provider | 提供者 | — |