本附件內容豐富。
D.1 總則
C# 為程式師提供了一種機制,以便使用包含 XML 文字的註釋語法來記錄其代碼。 在原始碼檔中,具有特定形式的註釋可用於指示工具從這些註釋及其前面的原始碼元素生成 XML。 使用此類語法的註釋稱為 文檔註釋。 它們必須緊跟在使用者定義的類型(如類、委託或介面)或成員(如欄位、事件、屬性或方法)之前。 XML 產生工具稱為 文檔產生器。 (此生成器可以是(但不一定是)C# 編譯器本身。文件生成器生成的輸出稱為 文件檔檔。 文件檔用作 文件檢視器的輸入;一種旨在生成類型資訊及其相關文檔的某種可視化顯示的工具。
符合要求的 C# 編譯器不需要檢查文檔註釋的語法;這樣的評論只是普通的評論。 但是,允許符合要求的編譯器執行此類檢查。
此規範建議在文檔註釋中使用一組標準標記,但不要求使用這些標記,並且只要遵循格式正確的 XML 規則,如果需要,可以使用其他標記。 對於面向 CLI 的 C# 實現,它還提供有關文檔生成器和文件檔案格式的資訊。 未提供有關文件查看器的資訊。
D.2 引言
具有特定形式的註釋可用於指示工具從這些註釋及其前面的原始碼元素生成 XML。 此類註釋是以三個斜杠 () 開頭的 Single_Line_Comments (///),或以一個斜杠和兩個星號 () 開頭的 Delimited_Comment(/**)。 它們必須緊跟在使用者定義的類型或它們批注的成員之前。 屬性區段 (§23.3) 會被視為宣告的一部分,因此檔註解必須先於套用至類型或成員的屬性。
出於說明目的,文檔註釋的格式如下所示為兩個語法規則: Single_Line_Doc_Comment 和 Delimited_Doc_Comment。 但是,這些規則 不是 C# 語法的一部分,而是分別表示 Single_Line_Comment 和 Delimited_Comment 詞法分析器規則的特定格式。
語法:
Single_Line_Doc_Comment
: '///' Input_Character*
;
Delimited_Doc_Comment
: '/**' Delimited_Comment_Section* ASTERISK+ '/'
;
在Single_Line_Doc_Comment中,如果當前Single_Line_Doc_Comment相鄰的每個///上的字元後面都有一個 Whitespace 字元,則該 Whitespace 字元不會包含在 XML 輸出中。
在 Delimited_Doc_Comment中,如果第二行上的第一個非空白 字元是 ASTERISK ,並且可選 空白 字元的相同模式,並且 ASTERISK 字元在 Delimited_Doc_Comment中每行的開頭重複,則重複模式的字元將不包含在 XML 輸出中。 該模式可以在 ASTERISK 字元之後和之前包含 Whitespace 字元。
範例︰
/// <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 格式不正確,則會生成警告,並且文檔檔將包含一條註釋,指出遇到了錯誤。
儘管開發人員可以自由創建自己的標籤集,但 §D.3 中定義了一組推薦的標籤。 某些建議標籤具有特殊意義:
該
<param>標籤用於描述參數。 如果使用此類標記,則文檔生成器必須驗證指定的參數是否存在,以及文檔註釋中是否描述了所有參數。 如果此類驗證失敗,文檔產生器將發出警告。cref屬性可以附加至任何標記,以提供程式碼項目的參考。 文件生成器必須驗證此代碼元素是否存在。 如果驗證失敗,文檔生成器會發出警告。 在查找屬性中描述的cref名稱時,文檔生成器必須根據原始碼中出現的using語句來考慮命名空間可見性。 對於泛型代碼元素,不能使用常規泛型語法(例如 “”“List<T>),因為它會生成無效的 XML。 可以使用大括弧代替括號(例如;“List{T}”),或者可以使用 XML 轉義語法(例如 “List<T>”)。該
<summary>標記旨在供文檔查看器用於顯示有關類型或成員的其他資訊。該
<include>標記包含來自外部 XML 檔案的資訊。
請仔細注意,文檔檔未提供有關類型和成員的完整資訊(例如,它不包含任何類型資訊)。 若要獲取有關類型或成員的此類資訊,必須將文檔檔與類型或成員的反射結合使用。
分部類型或分部方法可以在多個部分中聲明,每個部分可以位於一個或多個編譯單元中,並且每個部分都可以有一個或多個文檔註釋。 分部方法通常具有「定義部分聲明」和「實現部分聲明」。
對於分部類型,直接應用於該類型的文檔註釋(如果有)從其每個部分都以某種未指定的順序寫入文檔檔。
對於部分方法:
- 如果定義部分聲明沒有相應的實現部分聲明,則該定義部分聲明中的任何文檔註釋都將被忽略(因為該聲明將被刪除)。
- 否則,如果實現部分聲明具有任何文檔註釋,則會將其寫入文檔檔,並忽略定義部分聲明中的任何文檔註釋。
- 否則,定義 partial 聲明中的任何文件註釋都將寫入文檔檔。
D.3 推薦標籤
D.3.1 常規
文件生成器必須接受並處理根據 XML 規則有效的任何標記。 以下標籤提供了用戶文件中的常用功能。 (當然,其他標籤也是可能的。
| 標籤 | 參考 | 目的 |
|---|---|---|
<c> |
§D.3.2 | 以類似代碼的字體設置文字 |
<code> |
§D.3.3 | 設置一行或多行原始碼或程序輸出 |
<example> |
§D.3.4 | 指示示例 |
<exception> |
§D.3.5 | 標識方法可以引發的異常 |
<include> |
§D.3.6 | 包含來自外部檔的 XML |
<list> |
§D.3.7 | 創建清單或表格 |
<para> |
§D.3.8 | 允許將結構添加到文字中 |
<param> |
§D.3.9 | 描述方法或構造函數的參數 |
<paramref> |
§D.3.10 | 確定單詞是參數名稱 |
<permission> |
§D.3.11 | 記錄成員的安全可訪問性 |
<remarks> |
§D.3.12 | 描述有關類型的其他資訊 |
<returns> |
§D.3.13 | 描述方法的返回值 |
<see> |
§D.3.14 | 指定連結 |
<seealso> |
§D.3.15 | 生成 See Also 條目 |
<summary> |
§D.3.16 | 描述類型或類型的成員 |
<typeparam> |
§D.3.17 | 描述泛型類型或方法的類型參數 |
<typeparamref> |
§D.3.18 | 確定單詞是類型參數名稱 |
<value> |
§D.3.19 | 描述屬性 |
D.3.2 <丙>
此標記提供了一種機制,用於指示描述中的文本片段應設置為特殊字體,例如用於代碼塊的字體。 對於實際代碼的行數,請使用 <code> (§D.3.3)。
語法:
<c>
文字</c>
範例︰
/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
public class Point
{
}
D.3.3 <代碼>
此標籤用於以某種特殊字體設置一行或多行原始碼或程序輸出。 對於敘述中的小代碼片段,請使用 <c> (§D.3.2)。
語法:
<code>
原始碼或程序輸出</code>
範例︰
public class Point
{
/// <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 dx, int dy)
{
...
}
}
D.3.4 <示例>
此標籤允許註釋中的範例代碼指定如何使用方法或其他庫成員。 通常,這還涉及標籤 <code> (§D.3.3) 的使用。
語法:
<example>
描述</example>
範例︰
有關示例,請參見 <code> (§D.3.3)。
D.3.5 <異常>
此標記提供了一種記錄方法可以引發的異常。
語法:
<exception cref="
成員">描述</exception>
哪裡
-
cref="成員"是成員的名稱。 文件生成器會檢查給定成員是否存在,並將 member 轉換為文檔檔中的規範元素名稱。 - description 是對引發異常的情況的描述。
範例︰
class PrimaryFileFormatCorruptException : System.Exception { ... }
class PrimaryFileLockedOpenException : System.Exception { ... }
public class DataBaseOperations
{
/// <exception cref="PrimaryFileFormatCorruptException">
/// Thrown when the primary file is corrupted.
/// </exception>
/// <exception cref="PrimaryFileLockedOpenException">
/// Thrown when the primary file is already open.
/// </exception>
public static void ReadRecord(int flag)
{
if (flag == 1)
{
throw new PrimaryFileFormatCorruptException();
}
else if (flag == 2)
{
throw new PrimaryFileLockedOpenException();
}
...
}
}
D.3.6 <包括>
此標記允許包含原始程式碼檔案外部的 XML 文件中的資訊。 外部文件必須是格式正確的 XML 文件,並且 XPath 運算式將應用於該文件,以指定要包含該文件中的 XML。 然後,該 <include> 標記將替換為從外部文檔中選定的 XML。
語法:
<include file="
檔名" path="XPath 公司" />
哪裡
-
file="檔名"是外部 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 strings.
</summary>
</class>
</extradoc>
然後輸出相同的文件,就像原始程式碼包含一樣:
/// <summary>
/// Contains a list of integers.
/// </summary>
public class IntList { ... }
D.3.7 <列表>
這個標籤用於創建專案清單或表。 它可以包含一個 <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 是專案符號或編號清單中的項,或者是 術語的定義。
範例︰
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()
{
...
}
}
D.3.8 <para>
此標籤用於其他標籤,例如 <summary> (§D.3.16) 或 <returns> (§D.3.13),並允許將結構添加到文本中。
語法:
<para>
內容</para>
哪裡
- content 是段落的文本。
範例︰
public class Point
{
/// <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-trivial maintenance has
/// been performed on the Point class.
/// </para>
/// </summary>
public static void Main()
{
...
}
}
D.3.9 <參數>
此標記用於描述方法、構造函數或索引器的參數。
語法:
<param name="
名字">描述</param>
哪裡
- name 是參數的名稱。
- description 是參數的描述。
範例︰
public class Point
{
/// <summary>
/// This method changes the point's location to
/// the given coordinates.
/// </summary>
/// <param name="xPosition">the new x-coordinate.</param>
/// <param name="yPosition">the new y-coordinate.</param>
public void Move(int xPosition, int yPosition)
{
...
}
}
D.3.10 <參數引用>
此標籤用於指示單詞是參數。 可以處理文件檔檔,以某種不同的方式格式化此參數。
語法:
<paramref name="
名字"/>
哪裡
- name 是參數的名稱。
範例︰
public class Point
{
/// <summary>This constructor initializes the new Point to
/// (<paramref name="xPosition"/>,<paramref name="yPosition"/>).
/// </summary>
/// <param name="xPosition">the new Point's x-coordinate.</param>
/// <param name="yPosition">the new Point's y-coordinate.</param>
public Point(int xPosition, int yPosition)
{
...
}
}
D.3.11 <許可權>
此標記允許記錄成員的安全可訪問性。
語法:
<permission cref="
成員">描述</permission>
哪裡
- member 是成員的名稱。 文件生成器檢查給定的代碼元素是否存在,並將 member 轉換為文檔檔中的規範元素名稱。
- description 是對成員的訪問的描述。
範例︰
public class MyClass
{
/// <permission cref="System.Security.PermissionSet">
/// Everyone can access this method.
/// </permission>
public static void Test()
{
...
}
}
D.3.12 <備註>
此標籤用於指定有關類型的額外資訊。 使用 <summary> (§D.3.16) 描述類型本身和類型的成員。
語法:
<remarks>
描述</remarks>
哪裡
- description 是 remark 的文本。
範例︰
/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
/// <remarks>
/// Uses polar coordinates
/// </remarks>
public class Point
{
...
}
D.3.13 <返回>
此 tag 用於描述方法的返回值。
語法:
<returns>
描述</returns>
哪裡
- description 是返回值的描述。
範例︰
public class Point
{
/// <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() => $"({X},{Y})";
public int X { get; set; }
public int Y { get; set; }
}
D.3.14 <請參閱>
此標籤允許在文字中指定連結。 使用 <seealso> (§D.3.15) 指示要出現在 See Also 子子句中的文本。
語法:
<see cref="
成員" href="" langword="網址關鍵詞" />
哪裡
- member 是成員的名稱。 文件生成器檢查給定的代碼元素是否存在,並將 member 更改為生成的文件檔中的元素名稱。
- url 是對外部源的引用。
- langword 是一個需要以某種方式突出顯示的詞。
範例︰
public class Point
{
/// <summary>
/// This method changes the point's location to
/// the given coordinates. <see cref="Translate"/>
/// </summary>
public void Move(int xPosition, int yPosition)
{
...
}
/// <summary>This method changes the point's location by
/// the given x- and y-offsets. <see cref="Move"/>
/// </summary>
public void Translate(int dx, int dy)
{
...
}
}
D.3.15 <另請參閱>
此標記允許為 See Also 子子句生成條目。 使用 <see> (§D.3.14) 指定文本中的連結。
語法:
<seealso cref="
成員" href="網址" />
哪裡
- member 是成員的名稱。 文件生成器檢查給定的代碼元素是否存在,並將 member 更改為生成的文件檔中的元素名稱。
- url 是對外部源的引用。
範例︰
public class Point
{
/// <summary>
/// This method determines whether two Points have the same location.
/// </summary>
/// <seealso cref="operator=="/>
/// <seealso cref="operator!="/>
public override bool Equals(object o)
{
...
}
}
D.3.16 <摘要>
此標記可用於描述類型或類型的成員。 使用 <remarks> (§D.3.12) 指定有關類型或成員的額外資訊。
語法:
<summary>
描述</summary>
哪裡
- description 是 type 或 member 的摘要。
範例︰
public class Point
{
/// <summary>
/// This constructor initializes the new Point to
/// (<paramref name="xPosition"/>,<paramref name="yPosition"/>).
/// </summary>
public Point(int xPosition, int yPosition)
{
...
}
/// <summary>This constructor initializes the new Point to (0,0).</summary>
public Point() : this(0, 0)
{
}
}
D.3.17 <類型參數>
此標籤用於描述泛型類型或方法的類型參數。
語法:
<typeparam name="
名字">描述</typeparam>
哪裡
- name 是 type 參數的名稱。
- description 是 type 參數的描述。
範例︰
/// <summary>A generic list class.</summary>
/// <typeparam name="T">The type stored by the list.</typeparam>
public class MyList<T>
{
...
}
D.3.18 <類型paramref>
此標籤用於指示單詞是類型參數。 可以處理文件檔檔,以某種不同的方式格式化此類型參數。
語法:
<typeparamref name="
名字"/>
哪裡
- name 是 type 參數的名稱。
範例︰
public class MyClass
{
/// <summary>
/// This method fetches data and returns a list of
/// <typeparamref name="T"/>.
/// </summary>
/// <param name="query">query to execute</param>
public List<T> FetchData<T>(string query)
{
...
}
}
D.3.19 <值>
此標籤允許描述屬性。
語法:
<value>
屬性描述</value>
哪裡
- property description 是屬性的描述。
範例︰
public class Point
{
/// <value>Property <c>X</c> represents the point's x-coordinate.</value>
public int X { get; set; }
}
D.4 處理文件檔
D.4.1 常規
以下資訊適用於面向 CLI 的 C# 實現。
文件生成器為原始碼中標記有文件註釋的每個元素生成一個 ID 字串。 此ID字串唯一標識源元素。 文件查看器可以使用ID字串來標識文件所應用的相應專案。
文件檔不是原始碼的分層表示形式;相反,它是一個平面清單,其中包含為每個元素生成的ID字串。
D.4.2 ID 字串格式
文件產生器在產生 ID 字串時遵循以下規則:
字串中沒有空格符。
字串的第一部分通過單個字元後跟冒號標識要記錄的成員類型。 定義以下類型的成員:
字元 說明 E 事件 F 領域 M 方法(包括建構函數、終結器和運算子) N Namespace P 屬性(包括索引器) T 類型(例如 class、delegate、enum、interface 和 struct) ! 錯誤字串;字串的其餘部分提供有關錯誤的資訊。 例如,文件生成器會為無法解析的連結生成錯誤資訊。 字串的第二部分是元素的完全限定名稱,從命名空間的根開始。 元素的名稱、其封閉類型和命名空間用句點分隔。 如果專案本身的名稱包含句點,則它們將替換為 # (U+0023) 字元。 (假定任何元素的名稱中都沒有此字元。當成員顯式實現泛型介面的成員時,通過將周圍 “
<” 和 “>” 替換為 “{” 和 “”}字元來對完全限定名稱中的類型參數進行編碼。對於帶參數的方法和屬性,參數清單如下,括在括弧中。 對於沒有參數的 Bean,括弧被省略。 參數會以逗號分隔。 每個參數的編碼與 CLI 簽名相同,如下所示:
- 參數由其文件名稱表示,該名稱基於其完全限定名稱,修改如下:
- 表示泛型類型的參數附加了一個「
'字元,後跟類型參數的數量 - 具有
in,out或ref修飾符的參數在其類型名稱後面。@通過 value 或 viaparams傳遞的參數沒有特殊表示法。 - 作為陣列的參數表示為
[下限:大小,...,下限:大小]其中逗號的數量是排名減 1,每個維度的下限和大小(如果已知)以十進位表示。 如果未指定下限或大小,則省略該下限或大小。 如果省略特定維度的下限和大小,則也會省略 “”。:交錯陣列由每個級別一個 「表示[]」。 當下限為0(預設值)時,一維陣列會省略下限 (§17.1)。 - 指標類型不是
void的參數使用*類型名稱後面的 表示。void指標使用類型名稱System.Void表示。 - 引用類型上定義的泛型類型參數的參數使用 「
`字元進行編碼,後跟類型參數的從零開始的索引。 - 使用方法中定義的泛型類型參數的參數使用雙反引號 「
``而不是用於類型的」。」。。` - 引用構造泛型類型的參數使用泛型類型進行編碼,後跟 “
{”,後跟逗號分隔的類型參數清單,後跟 “}”。
- 表示泛型類型的參數附加了一個「
- 參數由其文件名稱表示,該名稱基於其完全限定名稱,修改如下:
D.4.3 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 }
}
class MyList<T>
{
class Helper<U,V> { ... }
}
}
編號:
"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"
"T:Acme.MyList`1"
"T:Acme.MyList`1.Helper`2"
欄位 由其完全限定名稱表示。
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, in int i) { ... }
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) { ... }
}
class MyList<T>
{
public void Test(T t) { ... }
}
class UseList
{
public void Process(MyList<int> list) { ... }
public MyList<T> GetValues<T>(T value) { ... }
}
}
編號:
"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@,System.Int32@)"
"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[])"
"M:Acme.MyList`1.Test(`0)"
"M:Acme.UseList.Process(Acme.MyList{System.Int32})"
"M:Acme.UseList.GetValues``1(``0)"
屬性和索引器
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_LogicalNotop_OnesComplementop_Incrementop_Decrementop_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_Additionop_Subtractionop_Multiplyop_Divisionop_Modulusop_BitwiseAndop_BitwiseOrop_ExclusiveOrop_LeftShiftop_RightShiftop_Equalityop_Inequalityop_LessThanop_LessThanOrEqualop_GreaterThanop_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"
D.5 示例
D.5.1 C# 原始程式碼
下面的示例顯示了 Point 類的原始碼:
namespace Graphics
{
/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
public class Point
{
/// <value>
/// Property <c>X</c> represents the point's x-coordinate.
/// </value>
public int X { get; set; }
/// <value>
/// Property <c>Y</c> represents the point's y-coordinate.
/// </value>
public int Y { get; set; }
/// <summary>
/// This constructor initializes the new Point to (0,0).
/// </summary>
public Point() : this(0, 0) {}
/// <summary>
/// This constructor initializes the new Point to
/// (<paramref name="xPosition"/>,<paramref name="yPosition"/>).
/// </summary>
/// <param name="xPosition">The new Point's x-coordinate.</param>
/// <param name="yPosition">The new Point's y-coordinate.</param>
public Point(int xPosition, int yPosition)
{
X = xPosition;
Y = yPosition;
}
/// <summary>
/// This method changes the point's location to
/// the given coordinates. <see cref="Translate"/>
/// </summary>
/// <param name="xPosition">The new x-coordinate.</param>
/// <param name="yPosition">The new y-coordinate.</param>
public void Move(int xPosition, int yPosition)
{
X = xPosition;
Y = yPosition;
}
/// <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).
/// <see cref="Move"/>
/// </example>
/// </summary>
/// <param name="dx">The relative x-offset.</param>
/// <param name="dy">The relative y-offset.</param>
public void Translate(int dx, int dy)
{
X += dx;
Y += dy;
}
/// <summary>
/// This method determines whether two Points have the same location.
/// </summary>
/// <param name="o">
/// The object to be compared to the current object.
/// </param>
/// <returns>
/// True if the Points have the same location and they have
/// the exact same type; otherwise, false.
/// </returns>
/// <seealso cref="operator=="/>
/// <seealso cref="operator!="/>
public override bool Equals(object o)
{
if (o == null)
{
return false;
}
if ((object)this == o)
{
return true;
}
if (GetType() == o.GetType())
{
Point p = (Point)o;
return (X == p.X) && (Y == p.Y);
}
return false;
}
/// <summary>
/// This method returns a Point's hashcode.
/// </summary>
/// <returns>
/// The int hashcode.
/// </returns>
public override int GetHashCode()
{
return X + (Y >> 4); // a crude version
}
/// <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, training, or embedded whitespace.
/// </returns>
public override string ToString() => $"({X},{Y})";
/// <summary>
/// This operator determines whether two Points have the same location.
/// </summary>
/// <param name="p1">The first Point to be compared.</param>
/// <param name="p2">The second Point to be compared.</param>
/// <returns>
/// True if the Points have the same location and they have
/// the exact same type; otherwise, false.
/// </returns>
/// <seealso cref="Equals"/>
/// <seealso cref="operator!="/>
public static bool operator==(Point p1, Point p2)
{
if ((object)p1 == null || (object)p2 == null)
{
return false;
}
if (p1.GetType() == p2.GetType())
{
return (p1.X == p2.X) && (p1.Y == p2.Y);
}
return false;
}
/// <summary>
/// This operator determines whether two Points have the same location.
/// </summary>
/// <param name="p1">The first Point to be compared.</param>
/// <param name="p2">The second Point to be compared.</param>
/// <returns>
/// True if the Points do not have the same location and the
/// exact same type; otherwise, false.
/// </returns>
/// <seealso cref="Equals"/>
/// <seealso cref="operator=="/>
public static bool operator!=(Point p1, Point p2) => !(p1 == p2);
}
}
D.5.2 生成的 XML
下面是一個文件生成器在給定類 Point的原始程式碼時生成的輸出,如上所示:
<?xml version="1.0"?>
<doc>
<assembly>
<name>Point</name>
</assembly>
<members>
<member name="T:Graphics.Point">
<summary>Class <c>Point</c> models a point in a two-dimensional
plane.
</summary>
</member>
<member name="M:Graphics.Point.#ctor">
<summary>This constructor initializes the new Point to (0, 0).</summary>
</member>
<member name="M:Graphics.Point.#ctor(System.Int32,System.Int32)">
<summary>
This constructor initializes the new Point to
(<paramref name="xPosition"/>,<paramref name="yPosition"/>).
</summary>
<param name="xPosition">The new Point's x-coordinate.</param>
<param name="yPosition">The new Point's y-coordinate.</param>
</member>
<member name="M:Graphics.Point.Move(System.Int32,System.Int32)">
<summary>
This method changes the point's location to
the given coordinates.
<see cref="M:Graphics.Point.Translate(System.Int32,System.Int32)"/>
</summary>
<param name="xPosition">The new x-coordinate.</param>
<param name="yPosition">The new y-coordinate.</param>
</member>
<member name="M:Graphics.Point.Translate(System.Int32,System.Int32)">
<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>
<see cref="M:Graphics.Point.Move(System.Int32,System.Int32)"/>
</summary>
<param name="dx">The relative x-offset.</param>
<param name="dy">The relative y-offset.</param>
</member>
<member name="M:Graphics.Point.Equals(System.Object)">
<summary>
This method determines whether two Points have the same location.
</summary>
<param name="o">
The object to be compared to the current object.
</param>
<returns>
True if the Points have the same location and they have
the exact same type; otherwise, false.
</returns>
<seealso
cref="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)" />
<seealso
cref="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)"/>
</member>
<member name="M:Graphics.Point.ToString">
<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, training, or embedded whitespace.
</returns>
</member>
<member name="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)">
<summary>
This operator determines whether two Points have the same location.
</summary>
<param name="p1">The first Point to be compared.</param>
<param name="p2">The second Point to be compared.</param>
<returns>
True if the Points have the same location and they have
the exact same type; otherwise, false.
</returns>
<seealso cref="M:Graphics.Point.Equals(System.Object)"/>
<seealso
cref="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)"/>
</member>
<member
name="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)">
<summary>
This operator determines whether two Points have the same location.
</summary>
<param name="p1">The first Point to be compared.</param>
<param name="p2">The second Point to be compared.</param>
<returns>
True if the Points do not have the same location and the
exact same type; otherwise, false.
</returns>
<seealso cref="M:Graphics.Point.Equals(System.Object)"/>
<seealso
cref="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)"/>
</member>
<member name="M:Graphics.Point.Main">
<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-trivial maintenance has
been performed on the Point class.
</para>
</summary>
</member>
<member name="P:Graphics.Point.X">
<value>
Property <c>X</c> represents the point's x-coordinate.
</value>
</member>
<member name="P:Graphics.Point.Y">
<value>
Property <c>Y</c> represents the point's y-coordinate.
</value>
</member>
</members>
</doc>
信息文字結尾。