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

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

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

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

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

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

      注意

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

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

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

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

注意

HTML 标记(如 <br/>)在文档注释中非常有用,可用于格式化。 该 <br/> 标记创建换行符,而其他 HTML 标记则提供文本格式。 这些标记适用于 IntelliSense 工具提示和生成的文档。

注意

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

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

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

常规标记

<总结>

<summary>description</summary>

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

<言论>

<remarks>
description
</remarks>

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

记录成员

<返回>

<returns>description</returns>

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

<参数>

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

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

<paramref>

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

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

<例外>

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

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

<价值>

<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/> 标记。

下面是一个示例,其中显示了以下两者之间的差异<para><br/>

/// <summary>
/// Example using para tags:
/// <para>This is the first paragraph.</para>
/// <para>This is the second paragraph with double spacing.</para>
/// 
/// Example using br tags:
/// First line of text<br/>
/// Second line of text with single spacing<br/>
/// Third line of text
/// </summary>
public void FormattingExample()
{
    // This method demonstrates paragraph and line break formatting
}

<列表>

<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>
    var index = 5;
    index++;
</code>

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

<例>

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

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

<b>

<b>text</b>

标记 <b> 用于在文档注释中加粗文本。 此 HTML 格式标记由编译器和 Visual Studio 验证,格式化文本将显示在 IntelliSense 和生成的文档中。

<我>

<i>text</i>

<i> 标记用于在文档注释中显示文本斜体。 此 HTML 格式标记由编译器和 Visual Studio 验证,格式化文本将显示在 IntelliSense 和生成的文档中。

<u>

<u>text</u>

标记 <u> 用于对文档注释中的文本进行下划线。 此 HTML 格式标记由编译器和 Visual Studio 验证,格式化文本将显示在 IntelliSense 和生成的文档中。

<br/>

Line one<br/>Line two

标记 <br/> 用于在文档注释中插入换行符。 如果需要一个空格段落,而不是 <para> 创建双间距段落的标记,请使用此标记。

<一个>

<a href="https://example.com">Link text</a>

标记 <a> 用于在文档注释中创建超链接。 该 href 属性指定要链接到的 URL。 编译器和 Visual Studio 验证此 HTML 格式设置标记。

注意

编译器还会验证 <tt> 标签,该标签在 HTML 中已被弃用。 请改用标签 <c> 进行内联代码格式化。

重用文档文本

<inheritdoc>

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

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

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

注意

Visual Studio 为重写或实现记录成员的未记录成员提供 XML 文档的自动继承。 此功能在 IntelliSense 和快速信息中显示继承的文档,而无需标记 <inheritdoc> 。 但是,此自动继承仅适用于 Visual Studio IDE,不会影响编译器生成的 XML 文档文件。

对于分发的库中的公共 API,应显式使用 <inheritdoc> 标记或提供完整的文档,以确保生成的 XML 文档文件包含库使用者所需的所有信息。

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

<包括>

<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 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。 使用 href 而不是 cref 来链接到外部网页,因为 cref 是为代码引用而设计的,不会为外部 URL 创建可点击的链接。
  • langword="keyword":语言关键字,例如 true 或其他有效关键字之一。

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

下面是一个示例,展示了引用外部 URL 时 crefhref 之间的差异。

/// <summary>
/// This method demonstrates URL linking:
/// <see cref="https://learn.microsoft.com/dotnet/csharp"/> (won't create clickable link)
/// <see href="https://learn.microsoft.com/dotnet/csharp">C# documentation</see> (creates clickable link)
/// </summary>
public void UrlLinkingExample()
{
    // This method demonstrates the difference between cref and href for URLs
}

<另见>

<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 或库的联机文档。 如果需要在文档注释中链接到外部 URL,请使用 href 而不是 cref,以确保这些链接在 IntelliSense 工具提示和生成的文档中可点击。

泛型类型和方法

<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 等多种输出格式。