建议用于 C# 文档注释的 XML 标记

C# 文档注释使用 XML 元素来定义输出文档的结构。 此功能的一个结果是可以在文档注释中添加任何有效的 XML。 C# 编译器会将这些元素复制到输出 XML 文件中。 虽然可以在注释中使用任何有效的 XML(包括任何有效的 HTML 元素),但出于许多原因,建议编制代码文档。

接下来将介绍一些建议、常规使用方案,以及在 C# 代码中使用 XML 文档标记时的需知内容。 虽然可以将任何标记放入文档注释中,但本文介绍了建议用于最常用语言构造的标记。 在所有情况下,都应遵循以下建议:

  • 为保持一致性,应编制所有公共可见类型及其公共成员的文档。
  • 还可使用 XML 注释编制私有成员的文档。 但这会公开库的内部(很可能是机密信息)运作情况。
  • 类型及其成员至少应该有一个 <summary> 标记。
  • 应使用句号结尾的完整句子编写文档文本。
  • 完全支持分部类,并且每个类型的文档信息会串联为单个条目。 如果分部成员的两个声明都有文档注释,则有关实现声明的注释将写入输出 XML。

XML 文档以 /// 开头。 创建新项目时,模板会放置一些以 /// 开头的行。 处理这些注释时存在一些限制:

  • 文档必须是格式正确的 XML。 如果 XML 格式不正确,编译器将生成警告。 文档文件包含一条注释,指出遇到错误。
  • 部分建议标记具有特殊含义:
    • <param> 标记用于描述参数。 如果已使用,编译器会验证该参数是否存在,以及文档是否描述了所有参数。 如果验证失败,编译器会发出警告。
    • cref 属性可以附加到任何标记,以引用代码元素。 编译器验证此代码元素是否存在。 如果验证失败,编译器会发出警告。 编译器在查找 cref 属性中描述的类型时会考虑 using 指令。
    • <summary> 标记由 Visual Studio 中的 IntelliSense 用于显示有关某个类型或成员的附加信息。

      注意

      XML 文件不提供有关该类型和成员的完整信息(例如,它不包含任何类型信息)。 若要获取有关类型或成员的完整信息,请将文档文件与对实际类型或成员的反射一起使用。

  • 开发人员可以随意创建自己的标记集。 编译器会将这些标记复制到输出文件。

部分建议的标记可用于任何语言元素。 其他建议的标记具有更特殊的用法。 最后,某些标记用于设置文档中文本的格式。 本文介绍了按用途整理的建议标记。

编译器验证以下列表中后跟单个 * 的元素的语法。 Visual Studio 为编译器验证的标记以及以下列表中后跟 ** 的所有标记提供 IntelliSense。 除此处列出的标记外,编译器和 Visual Studio 还验证 <b><i><u><br/><a> 标记。 编译器还会对已弃用的 <tt> 进行验证。

注意

不可对命名空间应用文档注释。

如果希望在文档注释的文本中显示尖括号,请使用 <> 的 HTML 编码,分别为 &lt;&gt;。 下面的示例对此编码进行了演示。

/// <summary>
/// This property always returns a value &lt; 1.
/// </summary>

常规标记

<summary>

<summary>description</summary>

<summary> 标记应当用于描述类型或类型成员。 使用 <remarks> 可针对某个类型说明添加补充信息。 使用 cref 属性可启用文档工具(如 DocFXSandcastle)来创建指向代码元素的文档页的内部超链接。 <summary> 标记的文本显示在 IntelliSense 和对象浏览器窗口中。

<remarks>

<remarks>
description
</remarks>

<remarks> 标记用于添加有关某个类型或某个类型成员的信息,从而补充由 <summary> 指定的信息。 此信息显示在对象浏览器窗口中。 此标记可能包含更冗长的说明。 你可能会发现,将 CDATA 部分用于 Markdown 可以更方便地进行编写。 docfx 等工具在 CDATA 部分中处理 Markdown 文本。

记录成员

<returns>

<returns>description</returns>

在方法声明的注释中应使用 <returns> 标记来描述返回值。

<param>

<param name="name">description</param>
  • name:方法参数的名称。 给名称加上引号 (")。 参数的名称必须与 API 签名匹配。 如果未涵盖一个或多个参数,编译器将发出警告。 如果 name 的值与方法声明中的正式参数不匹配,编译器也会发出警告。

在方法声明的注释中,应使用 <param> 标记来描述方法参数之一。 若要记录多个参数,请使用多个 <param> 标记。 <param> 标记的文本显示在 IntelliSense、对象浏览器和代码注释 Web 报表中。

<paramref>

<paramref name="name"/>
  • name:要引用的参数的名称。 给名称加上引号 (")。

<paramref> 标记提供一种方式,用于指示 <summary><remarks> 块等代码注释中的单词引用某个参数。 可以处理 XML 文件以明显的方式设置此单词的格式,如使用粗体或斜体。

<exception>

<exception cref="member">description</exception>
  • cref = "member":对当前编译环境中出现的一个异常的引用。 编译器检查是否存在给定的异常,并将 member 转换为输出 XML 中的规范的元素名称。 member 必须显示在引号 (") 内。

<exception> 标记可用于指定可引发的异常。 此标记可应用于方法、属性、事件和索引器的定义。

<value>

<value>property-description</value>

<value> 标记可用于描述属性表示的值。 在 Visual Studio .NET 开发环境中通过代码向导添加属性时,将添加新属性的 <summary> 标记。 可手动添加 <value> 标记,以描述属性表示的值。

设置文档输出格式

<para>

<remarks>
    <para>
        This is an introductory paragraph.
    </para>
    <para>
        This paragraph contains more details.
    </para>
</remarks>

<para> 标记在标记内使用,例如 <summary><remarks><returns>,并且你可用它来向文本添加结构。 <para> 标记创建一个双空格段落。 如果需要单空格段落,请使用 <br/> 标记。

<list>

<list type="bullet|number|table">
    <listheader>
        <term>term</term>
        <description>description</description>
    </listheader>
    <item>
        <term>Assembly</term>
        <description>The library or executable built from a compilation.</description>
    </item>
</list>

<listheader> 块用于定义表或定义列表的标题行。

定义表时:

  • 只需为标题中的 term 提供条目。
  • 列表中的每个项均使用 <item> 块指定。 对于每个 item,您只需为 description 提供一个条目。

创建定义列表时:

  • 必须为标题中的 term 提供条目。
  • 列表中的每个项均使用 <item> 块指定。 每个 item 必须同时包含 termdescription

列表或表可根据需要具有多个 <item> 块。

<c>

<c>text</c>

使用 <c> 标记可以指示应将说明内的文本标记为代码。 使用 <code> 指示作为代码的多行文本。

<code>

<code>
    var index = 5;
    index++;
</code>

<code> 标记用于指示多行代码。 使用 <c> 指示应将说明内的单行文本标记为代码。

<example>

<example>
This shows how to increment an integer.
<code>
    var index = 5;
    index++;
</code>
</example>

借助 <example> 标记,可以指定如何使用方法或其他库成员的示例。 示例通常涉及到使用 <code> 标记。

重用文档文本

<inheritdoc>

<inheritdoc [cref=""] [path=""]/>

继承基类、接口和类似方法中的 XML 注释。 使用 inheritdoc 不必复制和粘贴重复的 XML 注释,并自动保持 XML 注释同步。 将标记 <inheritdoc> 添加到类型时,所有成员也将继承注释。

  • cref:指定要向其继承文档的成员。 当前成员上已定义的标记不会被继承的标记重写。
  • path:导致显示节点集的 XPath 表达式查询。 可以使用此属性筛选要在继承文档中包含或排除的标记。

在基类或接口中添加 XML 注释,并让 inheritdoc 将注释复制到实现类中。 向同步方法添加 XML 注释,并让 inheritdoc 将注释复制到相同方法的异步版本中。 如果要从特定成员复制注释,可以使用 cref 特性来指定成员。

<include>

<include file='filename' path='tagpath[@name="id"]' />
  • filename:包含文档的 XML 文件的名称。 可使用相对于源代码文件的路径限定文件名。 使用单引号 (' ') 将 filename 括起来。
  • tagpathfilename 中标记的路径,它指向标记 name。 使用单引号 (' ') 将路径括起来。
  • name:标记中的名称说明符(位于注释之前);nameid
  • id:标记的 ID(位于注释之前)。 给 ID 加上引号 (")。

通过 <include> 标记,可在其他文件中引用描述源代码中类型和成员的注释。 包含外部文件是对直接在源代码文件中放入文档注释的替代方法。 通过将文档放入不同文件,可以单独从源代码对文档应用源控件。 一人可以签出源代码文件,而其他人可以签出文档文件。<include> 标记使用 XML XPath 语法。 有关如何自定义 <include> 用法的信息,请参阅 XPath 文档。

例如,以下源代码使用 <include> 标记来包含注解。 文件路径是相对于源的。

namespace MyNamespace;

public class MyType
{
    /// <returns>This is the returns text of MyMethod. It comes from triple slash comments.</returns>
    /// <remarks>This is the remarks text of MyMethod. It comes from triple slash comments.</remarks>
    /// <include file="MyAssembly.xml" path="doc/members/member[@name='M:MyNamespace.MyType.MyMethod']/*" />
    public int MyMethod(int p) => p;
}

包含文件的 XML 源代码显示在下面的示例中。 它的结构与 C# 编译器生成的 XML 文件相同。 XML 文件可以包含多个方法或类型的文本,只要 XPath 表达式可识别它们。

<?xml version="1.0"?>
<doc>
    <members>
        <member name="M:MyNamespace.MyType.MyMethod">
            <param name="p">This is the description of the parameter p of MyMethod. It comes from the included file.</param>
            <summary>This is the summary of MyMethod. It comes from the included file.</summary>
        </member>
    </members>
</doc>

此方法的 XML 输出如以下示例所示:

<member name="M:MyNamespace.MyType.MyMethod(System.Int32)">
    <summary>This is the summary of MyMethod. It comes from the included file.</summary>
    <returns>This is the returns text of MyMethod. It comes from triple slash comments.</returns>
    <remarks>This is the remarks text of MyMethod. It comes from triple slash comments.</remarks>
    <param name="p">This is the description of the parameter p of MyMethod. It comes from the included file.</param>
</member>

提示

.NET 运行时团队在文档中广泛使用了 <include> 标记。 通过搜索 dotnet/runtime 存储库,可以看到许多示例。

<see>

<see cref="member"/>
<!-- or -->
<see cref="member">Link text</see>
<!-- or -->
<see href="link">Link Text</see>
<!-- or -->
<see langword="keyword"/>
  • cref="member":对可从当前编译环境调用的成员或字段的引用。 编译器检查是否存在给定的码位元素,并将 member 传递到输出 XML 中的元素名称。 将成员置于引号 (") 内。 可以使用单独的结束标记为“cref”提供不同的链接文本。
  • href="link":指向给定 URL 的可单击链接。 例如,<see href="https://github.com">GitHub</see> 生成一个可单击的链接,其中包含文本 GitHub,该文本链接到 https://github.com
  • langword="keyword":语言关键字,例如 true 或其他有效关键字之一。

<see> 标记可用于从文本内指定链接。 使用 <seealso> 指示文本应该放在“另请参阅”部分中。 使用 cref 属性创建指向代码元素的文档页的内部超链接。 包含类型参数以指定对泛型类型或方法(如 cref="IDictionary{T, U}")的引用。 此外,href 还是一个有效属性,用作超链接。

<seealso>

<seealso cref="member"/>
<!-- or -->
<seealso href="link">Link Text</seealso>
  • cref="member":对可从当前编译环境调用的成员或字段的引用。 编译器检查是否存在给定的码位元素,并将 member 传递到输出 XML 中的元素名称。 member 必须显示在引号 (") 内。
  • href="link":指向给定 URL 的可单击链接。 例如,<seealso href="https://github.com">GitHub</seealso> 生成一个可单击的链接,其中包含文本 GitHub,该文本链接到 https://github.com

使用 <seealso> 标记,可以指定想要在另请参阅部分中显示的文本。 使用 <see> 从文本内指定链接。 不能将 seealso 标记嵌套在 summary 标记内。

cref 特性

XML 文档标记中的 cref 属性表示“代码引用”。它指定标记的内部文本是代码元素,例如类型、方法或属性。 文档工具(例如 DocFXSandcastle)使用 cref 属性自动生成指向记录类型或成员的页面的超链接。

href 特性

href 特性表示对网页的引用。 可以使用它直接引用有关 API 或库的联机文档。

泛型类型和方法

<typeparam>

<typeparam name="TResult">The type returned from this method</typeparam>
  • TResult:类型参数的名称。 给名称加上引号 (")。

在泛型类型或方法声明的注释中,应使用 <typeparam> 标记来描述类型参数。 为泛型类型或方法的每个类型参数添加标记。 <typeparam> 标记的文本显示在 IntelliSense 中。

<typeparamref>

<typeparamref name="TKey"/>
  • TKey:类型参数的名称。 给名称加上引号 (")。

通过此标记,文档文件的使用者可显著设置字体格式,例如采用斜体。

用户定义的标记

本文概述的所有标记均表示由 C# 编译器识别的标记。 但用户可随意定义自己的标记。 Sandcastle 等工具支持其他标记,例如 <event><note>,甚至支持编制命名空间文档。 自定义或内部文档生成工具也可与标准标记配合使用,并支持 HTML 到 PDF 等多种输出格式。