C# 提供一種機制,使程序員可使用含有 XML 文本的特殊註釋語法爲他們的代碼編寫文檔。在源代碼文件中,具備某種格式的註釋可用於指導某個工具根據這些註釋和它們後面的源代碼元素生成 XML。使用這類語法的註釋稱爲文檔註釋(documentation comment)。這些註釋後面必須緊跟用戶定義類型(如類、委託或接口)或者成員(如字段、事件、屬性或方法)。XML 生成工具稱做文檔生成器 (documentation generator)。(今生成器能夠但不必定必須是 C# 編譯器自己。)由文檔生成器產生的輸出稱爲文檔文件 (documentation file)。文檔文件可做爲文檔查看器 (documentation viewer) 的輸入;文檔查看器是用於生成類型信息及其關聯文檔的某種可視化顯示的工具。html
此規範推薦了一組在文檔註釋中使用的標記,可是這些標記不是必須使用的,若是須要也可使用其餘標記,只要遵循「符合格式標準的 XML」規則便可。程序員
A.1. 介紹數組
具備特殊格式的註釋可用於指導某個工具根據這些註釋和它們後面的源代碼元素生成 XML。這類註釋是以三個斜槓 (///) 開始的單行註釋,或者是以一個斜槓和兩個星號 (/**) 開始的分隔註釋。這些註釋後面必須緊跟它們所註釋的用戶定義類型(如類、委託或接口)或者成員(如字段、事件、屬性或方法)。屬性節(第 17.2 節)被視爲聲明的一部分,所以,文檔註釋必須位於應用到類型或成員的屬性以前。安全
語法:ide
single-line-doc-comment:
/// input-charactersopt函數
delimited-doc-comment:
/** delimited-comment-charactersopt */工具
在 single-line-doc-comment 中,若是當前 single-line-doc-comment 旁邊的每一個 single-line-doc-comment 上的 /// 字符後跟有 whitespace 字符,則此 whitespace 字符不包括在 XML 輸出中。字體
在 delimited-doc-comment 中,若是第二行上的第一個非 whitespace 字符是一個 asterisk,而且在 delimited-doc-comment 內的每行開頭都重複同一個由可選 whitespace 字符和 asterisk 字符組成的樣式,則該重複出現的樣式所含的字符不包括在 XML 輸出中。此樣式中,能夠在 asterisk 字符以前或以後包括 whitespace 字符。this
示例:編碼
/// <summary>Class <c>Point</c> models a point in a two-dimensional
/// plane.</summary>
///
public class Point
{
/// <summary>method <c>draw</c> renders the point.</summary>
void draw() {…}
}
文檔註釋內的文本必須根據 XML 規則 (http://www.w3.org/TR/REC-xml) 設置正確的格式。若是 XML 不符合標準格式,將生成警告,而且文檔文件將包含一條註釋,指出遇到錯誤。
儘管開發人員可自由建立它們本身的標記集,但第 A.2 節定義有建議的標記集。某些建議的標記具備特殊含義:
· <param> 標記用於描述參數。若是使用這樣的標記,文檔生成器必須驗證指定參數是否存在以及文檔註釋中是否描述了全部參數。若是此驗證失敗,文檔生成器將發出警告。
· cref 屬性能夠附加到任意標記,以提供對代碼元素的參考。文檔生成器必須驗證此代碼元素是否存在。若是驗證失敗,文檔生成器將發出警告。查找在 cref 屬性中描述的名稱時,文檔生成器必須根據源代碼中出現的 using 語句來考慮命名空間的可見性。
· <summary> 標記旨在標出可由文檔查看器顯示的有關類型或成員的額外信息。
· <include> 標記表示應該包含的來自外部 XML 文件的信息。
注意,文檔文件並不提供有關類型和成員的完整信息(例如,它不包含任何關於類型的信息)。若要得到有關類型或成員的完整信息,必須協同使用文檔文件與對實際涉及的類型或成員的反射調用。
文檔生成器必須接受和處理任何根據 XML 規則有效的標記。下列標記提供了用戶文檔中經常使用的功能。(固然,也可能有其餘標記。)
標記
章節
用途
<c>
A.2.1
將文本設置爲相似代碼的字體
<code>
A.2.2
將一行或多行源代碼或程序輸出設置爲某種字體
<example>
A.2.3
表示所含的是示例
<exception>
A.2.4
標識方法可能引起的異常
<include>
A.2.5
包括來自外部文件的 XML
<list>
A.2.6
建立列表或表
<para>
A.2.7
用於將結構添加到文本中
<param>
A.2.8
描述方法或構造函數的參數
<paramref>
A.2.9
確認某個單詞是參數名
<permission>
A.2.10
描述成員的安全性和訪問權限
<summary>
A.2.11
描述一種類型
<returns>
A.2.12
描述方法的返回值
<see>
A.2.13
指定連接
<seealso>
A.2.14
生成「請參見」項
<summary>
A.2.15
描述類型的成員
<value>
A.2.16
描述屬性
此標記提供一種機制以指示用特殊字體(如用於代碼塊的字體)設置說明中的文本段落。對於實際代碼行,請使用 <code>(第 A.2.2 節)。
語法:
<c>text</c>
示例:
/// <summary>Class <c>Point</c> models a point in a two-dimensional
/// plane.</summary>
public class Point
{
// ...
}
此標記用於將一行或多行源代碼或程序輸出設置爲某種特殊字體。對於敘述中較小的代碼段,請使用 <c>(第 A.2.1 節)。
語法:
<code>source code or program output</code>
示例:
/// <summary>This method changes the point's location by
/// the given x- and y-offsets.
/// <example>For example:
/// <code>
/// Point p = new Point(3,5);
/// p.Translate(-1,3);
/// </code>
/// results in <c>p</c>'s having the value (2,8).
/// </example>
/// </summary>
public void Translate(int xor, int yor) {
X += xor;
Y += yor;
}
此標記用於在註釋中插入代碼示例,以說明如何使用所關聯的方法或其餘庫成員。一般,此標記是同標記 <code>(第 A.2.2 節)一塊兒使用的。
語法:
<example>description</example>
示例:
有關示例,請參見 <code>(第 A.2.2 節)。
此標記提供一種方法以說明關聯的方法可能引起的異常。
語法:
<exception cref="member">description</exception>
其中
cref="member"
成員的名稱。文檔生成器檢查給定成員是否存在,並將 member 轉換爲文檔文件中的規範元素名稱。
description
對引起異常的狀況的描述。
示例:
public class DataBaseOperations
{
/// <exception cref="MasterFileFormatCorruptException"></exception>
/// <exception cref="MasterFileLockedOpenException"></exception>
public static void ReadRecord(int flag) {
if (flag == 1)
throw new MasterFileFormatCorruptException();
else if (flag == 2)
throw new MasterFileLockedOpenException();
// …
}
}
此標記容許包含來自源代碼文件外部的 XML 文檔的信息。外部文件必須是符合標準格式的 XML 文檔,還能夠將 XPath 表達式應用於該文檔來指定應包含該 XML 文檔中的哪些 XML 文本。而後用從外部文檔中選定的 XML 來替換 <include>標記。
語法:
<include file="filename" path="xpath" />
其中
file="filename"
外部 XML 文件的文件名。該文件名是相對於包含 include 標記的文件進行解釋的(肯定其完整路徑名)。
path="xpath"
XPath 表達式,用於選擇外部 XML 文件中的某些 XML。
示例:
若是源代碼包含了以下聲明:
/// <include file="docs.xml" path='extradoc/class[@name="IntList"]/*' />
public class IntList { … }
而且外部文件「docs.xml」含有如下內容:
<?xml version="1.0"?>
<extradoc>
<class name="IntList">
<summary>
Contains a list of integers.
</summary>
</class>
<class name="StringList">
<summary>
Contains a list of integers.
</summary>
</class>
</extradoc>
這樣輸出的文檔就與源代碼中包含如下內容時同樣:
/// <summary>
/// Contains a list of integers.
/// </summary>
public class IntList { … }
此標記用於建立列表或項目表。它能夠包含 <listheader> 塊以定義表或定義列表的標頭行。(定義表時,僅須要在標頭中爲 term 提供一個項。)
列表中的每一項都用一個 <item> 塊來描述。建立定義列表時,必須同時指定 term 和 description。可是,對於表、項目符號列表或編號列表,僅須要指定 description。
語法:
<list type="bullet" | "number" | "table">
<listheader>
<term>term</term>
<description>description</description>
</listheader>
<item>
<term>term</term>
<description>description</description>
</item>
…
<item>
<term>term</term>
<description>description</description>
</item>
</list>
其中
term
要定義的術語,其定義位於 description 中。
description
是項目符號列表或編號列表中的項,或者是 term 的定義。
示例:
public class MyClass
{
/// <summary>Here is an example of a bulleted list:
/// <list type="bullet">
/// <item>
/// <description>Item 1.</description>
/// </item>
/// <item>
/// <description>Item 2.</description>
/// </item>
/// </list>
/// </summary>
public static void Main () {
// ...
}
}
此標記用於其餘標記內,如 <summary>(第 A.2.11 節)或 <returns>(第 A.2.12 節),用於將結構添加到文本中。
語法:
<para>content</para>
其中
content
段落文本。
示例:
/// <summary>This is the entry point of the Point class testing program.
/// <para>This program tests each method and operator, and
/// is intended to be run after any non-trvial maintenance has
/// been performed on the Point class.</para></summary>
public static void Main() {
// ...
}
該標記用於描述方法、構造函數或索引器的參數。
語法:
<param name="name">description</param>
其中
name
參數名。
description
參數的描述。
示例:
/// <summary>This method changes the point's location to
/// the given coordinates.</summary>
/// <param name="xor">the new x-coordinate.</param>
/// <param name="yor">the new y-coordinate.</param>
public void Move(int xor, int yor) {
X = xor;
Y = yor;
}
該標記表示某單詞是一個參數。這樣,生成文檔文件後經適當處理,能夠用某種獨特的方法來格式化該參數。
語法:
<paramref name="name"/>
其中
name
參數名。
示例:
/// <summary>This constructor initializes the new Point to
/// (<paramref name="xor"/>,<paramref name="yor"/>).</summary>
/// <param name="xor">the new Point's x-coordinate.</param>
/// <param name="yor">the new Point's y-coordinate.</param>
public Point(int xor, int yor) {
X = xor;
Y = yor;
}
該標記用於將成員的安全性和可訪問性記入文檔。
語法:
<permission cref="member">description</permission>
其中
cref="member"
成員的名稱。文檔生成器檢查給定的代碼元素是否存在,並將 member 轉換爲文檔文件中的規範化元素名稱。
description
對成員的訪問屬性的說明。
示例:
/// <permission cref="System.Security.PermissionSet">Everyone can
/// access this method.</permission>
public static void Test() {
// ...
}
該標記用於指定類型的概述信息。(使用 <summary>(第 A.2.15 節)描述類型的成員。)
語法:
<summary>description</summary>
其中
description
摘要文本。
示例:
/// <summary>Class <c>Point</c> models a point in a
/// two-dimensional plane.</summary>
public class Point
{
// ...
}
該標記用於描述方法的返回值。
語法:
<returns>description</returns>
其中
description
返回值的說明。
示例:
/// <summary>Report a point's location as a string.</summary>
/// <returns>A string representing a point's location, in the form (x,y),
/// without any leading, trailing, or embedded whitespace.</returns>
public override string ToString() {
return "(" + X + "," + Y + ")";
}
該標記用於在文本內指定連接。使用 <seealso>(第 A.2.14 節)指示將在「請參見」部分中出現的
文本。
語法:
<see cref="member"/>
其中
cref="member"
成員的名稱。文檔生成器檢查給定的代碼元素是否存在,並將 member 更改成所生成的文檔文件中的元素名稱。
示例:
/// <summary>This method changes the point's location to
/// the given coordinates.</summary>
/// <see cref="Translate"/>
public void Move(int xor, int yor) {
X = xor;
Y = yor;
}
/// <summary>This method changes the point's location by
/// the given x- and y-offsets.
/// </summary>
/// <see cref="Move"/>
public void Translate(int xor, int yor) {
X += xor;
Y += yor;
}
該標記用於生成將列入「請參見」部分的項。使用 <see>(第 A.2.13 節)指定來自文本內的連接。
語法:
<seealso cref="member"/>
其中
cref="member"
成員的名稱。文檔生成器檢查給定的代碼元素是否存在,並將 member 更改成所生成的文檔文件中的元素名稱。
示例:
/// <summary>This method determines whether two Points have the same
/// location.</summary>
/// <seealso cref="operator=="/>
/// <seealso cref="operator!="/>
public override bool Equals(object o) {
// ...
}
能夠用此標記描述類型的成員。使用 <summary>(第 A.2.11 節)描述類型自己。
語法:
<summary>description</summary>
其中
description
關於成員的摘要描述。
示例:
/// <summary>This constructor initializes the new Point to (0,0).</summary>
public Point() : this(0,0) {
}
該標記用於描述屬性。
語法:
<value>property description</value>
其中
property description
屬性的說明。
示例:
/// <value>Property <c>X</c> represents the point's x-coordinate.</value>
public int X
{
get { return x; }
set { x = value; }
}
A.3. 處理文檔文件
文檔生成器爲源代碼中每一個附加了「文檔註釋標記」的代碼元素生成一個 ID 字符串。該 ID 字符串惟一地標識源元素。文檔查看器利用此 ID 字符串來標識該文檔所描述的對應的元數據/反射項。
文檔文件不是源代碼的層次化表現形式;而是爲每一個元素生成的 ID 字符串的一維列表。
A.3.1. ID 字符串格式
文檔生成器在生成 ID 字符串時遵循下列規則:
· 不在字符串中放置空白。
· 字符串的第一部分經過單個字符後跟一個冒號來標識被標識成員的種類。定義如下幾種成員:
字符
說明
E
事件
F
字段
M
方法(包括構造函數、析構函數和運算符)
N
命名空間
P
屬性(包括索引器)
T
類型(如類、委託、枚舉、接口和結構)
!
錯誤字符串;字符串的其餘部分提供有關錯誤的信息。例如,文檔生成器對沒法解析的連接生成錯誤信息。
· 字符串的第二部分是元素的徹底限定名,從命名空間的根開始。元素的名稱、包含着它的類型和命名空間都以句點分隔。若是項名自己含有句點,則將用 # (U+0023) 字符替換。(這裏假定全部元素名中都沒有「# (U+0023)」字符。)
· 對於帶有參數的方法和屬性,接着是用括號括起來的參數列表。對於那些不帶參數的方法和屬性,則省略括號。多個參數以逗號分隔。每一個參數的編碼都與 CLI 簽名相同,以下所示:參數由其徹底限定名來表示。例如,int 變成System.Int3二、string 變成 System.String、object 變成 System.Object 等。具備 out 或 ref 修飾符的參數在其類型名後跟有 @ 符。對於由值傳遞或經過 params 傳遞的參數沒有特殊表示法。數組參數表示爲 [ lowerbound : size , … ,lowerbound : size ],其中逗號數量等於秩減去一,而下限和每一個維的大小(若是已知)用十進制數表示。若是未指定下限或大小,它將被省略。若是省略了某個特定維的下限及大小,則「:」也將被省略。交錯數組由每一個級別一個「[]」來表示。指針類型爲非 void 的參數用類型名後面跟一個 * 的形式來表示。void 指針用類型名 System.Void 表示。
A.3.2. ID 字符串示例
下列各個示例分別演示一段 C# 代碼以及爲每一個能夠含有文檔註釋的源元素生成的 ID 字符串:
· 類型用它們的徹底限定名來表示。
enum Color { Red, Blue, Green }
namespace Acme
{
interface IProcess {...}
struct ValueType {...}
class Widget: IProcess
{
public class NestedClass {...}
public interface IMenuItem {...}
public delegate void Del(int i);
public enum Direction { North, South, East, West }
}
}
"T:Color"
"T:Acme.IProcess"
"T:Acme.ValueType"
"T:Acme.Widget"
"T:Acme.Widget.NestedClass"
"T:Acme.Widget.IMenuItem"
"T:Acme.Widget.Del"
"T:Acme.Widget.Direction"
· 字段用它們的徹底限定名來表示。
namespace Acme
{
struct ValueType
{
private int total;
}
class Widget: IProcess
{
public class NestedClass
{
private int value;
}
private string message;
private static Color defaultColor;
private const double PI = 3.14159;
protected readonly double monthlyAverage;
private long[] array1;
private Widget[,] array2;
private unsafe int *pCount;
private unsafe float **ppValues;
}
}
"F:Acme.ValueType.total"
"F:Acme.Widget.NestedClass.value"
"F:Acme.Widget.message"
"F:Acme.Widget.defaultColor"
"F:Acme.Widget.PI"
"F:Acme.Widget.monthlyAverage"
"F:Acme.Widget.array1"
"F:Acme.Widget.array2"
"F:Acme.Widget.pCount"
"F:Acme.Widget.ppValues"
· 構造函數。
namespace Acme
{
class Widget: IProcess
{
static Widget() {...}
public Widget() {...}
public Widget(string s) {...}
}
}
"M:Acme.Widget.#cctor"
"M:Acme.Widget.#ctor"
"M:Acme.Widget.#ctor(System.String)"
· 析構函數。
namespace Acme
{
class Widget: IProcess
{
~Widget() {...}
}
}
"M:Acme.Widget.Finalize"
· 方法。
namespace Acme
{
struct ValueType
{
public void M(int i) {...}
}
class Widget: IProcess
{
public class NestedClass
{
public void M(int i) {...}
}
public static void M0() {...}
public void M1(char c, out float f, ref ValueType v) {...}
public void M2(short[] x1, int[,] x2, long[][] x3) {...}
public void M3(long[][] x3, Widget[][,,] x4) {...}
public unsafe void M4(char *pc, Color **pf) {...}
public unsafe void M5(void *pv, double *[][,] pd) {...}
public void M6(int i, params object[] args) {...}
}
}
"M:Acme.ValueType.M(System.Int32)"
"M:Acme.Widget.NestedClass.M(System.Int32)"
"M:Acme.Widget.M0"
"M:Acme.Widget.M1(System.Char,System.Single@,Acme.ValueType@)"
"M:Acme.Widget.M2(System.Int16[],System.Int32[0:,0:],System.Int64[][])"
"M:Acme.Widget.M3(System.Int64[][],Acme.Widget[0:,0:,0:][])"
"M:Acme.Widget.M4(System.Char*,Color**)"
"M:Acme.Widget.M5(System.Void*,System.Double*[0:,0:][])"
"M:Acme.Widget.M6(System.Int32,System.Object[])"
· 屬性和索引器。
namespace Acme
{
class Widget: IProcess
{
public int Width { get {...} set {...} }
public int this[int i] { get {...} set {...} }
public int this[string s, int i] { get {...} set {...} }
}
}
"P:Acme.Widget.Width"
"P:Acme.Widget.Item(System.Int32)"
"P:Acme.Widget.Item(System.String,System.Int32)"
· 事件。
namespace Acme
{
class Widget: IProcess
{
public event Del AnEvent;
}
}
"E:Acme.Widget.AnEvent"
· 一元運算符。
namespace Acme
{
class Widget: IProcess
{
public static Widget operator+(Widget x) {...}
}
}
"M:Acme.Widget.op_UnaryPlus(Acme.Widget)"
下面列出可以使用的一元運算符函數名稱的完整集合:op_UnaryPlus、op_UnaryNegation、op_LogicalNot、op_OnesComplement、op_Increment、op_Decrement、op_True 和 op_False。
· 二元運算符。
namespace Acme
{
class Widget: IProcess
{
public static Widget operator+(Widget x1, Widget x2) {...}
}
}
"M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget)"
下面列出可以使用的二元運算符函數名稱的完整集合:op_Addition、op_Subtraction、op_Multiply、op_Division、op_Modulus、op_BitwiseAnd、op_BitwiseOr、op_ExclusiveOr、op_LeftShift、op_RightShift、op_Equality、op_Inequality、op_LessThan、op_LessThanOrEqual、op_GreaterThan 和 op_GreaterThanOrEqual。
· 轉換運算符具備一個尾隨「~」,而後再跟返回類型。
namespace Acme
{
class Widget: IProcess
{
public static explicit operator int(Widget x) {...}
public static implicit operator long(Widget x) {...}
}
}
"M:Acme.Widget.op_Explicit(Acme.Widget)~System.Int32"
"M:Acme.Widget.op_Implicit(Acme.Widget)~System.Int64"
引用: https://www.cnblogs.com/cccc/archive/2009/08/19/1549866.html