附錄 D 檔批注
這份附件具有資訊性。
D.1 一般
C# 提供一種機制,讓程式設計人員使用包含 XML 文字的批註語法來記錄其程式代碼。 在原始碼檔案中,具有特定表單的批註可用來指示工具從這些批注產生 XML,以及它們前面的原始碼元素。 使用這類語法的批注稱為 檔批注。 它們必須緊接在使用者定義型別之前(例如類別、委派或介面)或成員(例如欄位、事件、屬性或方法)。 XML 產生工具稱為 檔案產生器。 (此產生器可以是 C# 編譯程式本身,但不需要。檔產生器所產生的輸出稱為檔案檔案。 檔檔會用來做為檔查看器的輸入;工具旨在產生某種類型的視覺顯示資訊及其相關文件。
不需要符合 C# 編譯程式,即可檢查檔批注的語法;這類批注只是普通的批注。 不過,允許符合規範的編譯程序進行這類檢查。
此規格建議在檔批註中使用一組標準標記,但不需要使用這些標籤,只要遵循格式正確的 XML 規則,就可以使用其他標籤。 針對以 CLI 為目標的 C# 實作,它也會提供文件產生器和文件檔格式的相關信息。 檔查看器未提供任何相關信息。
D.2 簡介
具有特定表單的批註可用來指示工具從這些批注產生 XML,以及它們前面的原始程式碼元素。 這些評論以三個斜線(),或以斜線和兩個星號 () 開頭的Single_Line_Comment s (///
~6.3.3) 或Delimited_Comments (~6.3.3) 開頭的批注。/**
他們必須緊接在使用者定義型別之前,或是標註的成員。 屬性區段 ({22.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_Comments與目前Single_Line_Doc_Comment相鄰的字元有空格符///
,則該空格符不會包含在 XML 輸出中。
在Delimited_Doc_Comment中,如果第二行的第一個非空格符是 ASTERISK,且選擇性空格符的相同模式和 ASTERISK 字元會在Delimited_Doc_Comment內的每一行開頭重複,則重複模式的字元不會包含在 XML 輸出中。 此模式可以包含 後置 空格符,以及之前 ASTERISK 字元。
範例:
/// <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 檔案的資訊。
請注意,文件檔不會提供類型和成員的完整資訊(例如,它不包含任何類型資訊)。 若要取得類型或成員的這類資訊,檔案檔案必須與類型或成員的反映搭配使用。
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 | 產生另一個專案 |
<summary> |
•D.3.16 | 描述類型或型別的成員 |
<typeparam> |
•D.3.17 | 描述泛型型別或方法的類型參數 |
<typeparamref> |
•D.3.18 | 識別單字是類型參數名稱 |
<value> |
•D.3.19 | 描述屬性 |
D.3.2 <c>
此標籤提供一種機制,指出描述中的文字片段應該以特殊字型設定,例如用於程式代碼區塊。 針對實際程式代碼行,請使用 <code>
(~D.3.3)。
語法:
<c>
text</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>
description</example>
範例:
如需範例,請參閱 <code>
(\D.3.3)。
D.3.5 <例外狀況>
此標籤提供一種方式來記錄方法可以擲回的例外狀況。
語法:
<exception cref="
成員">
描述</exception>
where
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="
filename" path="
xpath" />
where
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 strings.
</summary>
</class>
</extradoc>
然後,相同的檔案會輸出,就像原始程式碼包含:
/// <summary>
/// Contains a list of integers.
/// </summary>
public class IntList { ... }
D.3.7 <列表>
此標記是用來建立專案清單或數據表。 它可以包含區塊 <listheader>
來定義資料表或定義清單的標題數據列。 (定義數據表時,只需要提供標題中的字詞專案。
清單中的每個項目都是使用 <item>
區塊所指定。 建立定義清單時, 必須同時指定字詞 和 描述 。 不過,針對數據表、點符清單或編號清單,只需要 指定描述 。
語法:
<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>
where
- term 是要定義的字詞,其定義在描述中。
- 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>
where
- 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>
這個標記可用來描述方法、建構函式或索引器的參數。
語法:
<param name="
名稱">
描述</param>
where
- 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>
這個標記用來指出單字是參數。 檔檔可以處理成以某種不同方式格式化此參數。
語法:
<paramref name="
name"/>
where
- 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>
where
- 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>
description</remarks>
where
- description 是備註的文字。
範例:
/// <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 <傳回>
這個標記可用來描述方法的傳回值。
語法:
<returns>
description</returns>
where
- 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 cref="
成員" href="
URL" langword="
關鍵詞" />
where
- member 是成員的名稱。 檔案產生器會檢查指定的程式代碼專案是否存在,並將成員變更為產生的檔檔中的項目名稱。
- url 是外部來源的參考。
- 俚語 是一個以某種方式醒目提示的字。
範例:
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 <seealso>
此卷標允許為 See Also 子程式產生專案。 使用 <see>
(~D.3.14) 從文字中指定連結。
語法:
<seealso cref="
成員" href="
URL" />
where
- 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>
description</summary>
where
- description 是類型或成員的摘要。
範例:
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>
這個標記可用來描述泛型類型或方法的類型參數。
語法:
<typeparam name="
名稱">
描述</typeparam>
where
- name 是類型參數的名稱。
- description 是類型參數的描述。
範例:
/// <summary>A generic list class.</summary>
/// <typeparam name="T">The type stored by the list.</typeparam>
public class MyList<T>
{
...
}
D.3.18 <typeparamref>
這個標記用來指出單字是類型參數。 檔檔可以處理成以某種不同方式格式化此類型參數。
語法:
<typeparamref name="
name"/>
where
- name 是類型參數的名稱。
範例:
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>
where
- 屬性描述 是 屬性的描述。
範例:
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# 實作。
檔產生器會針對原始碼中標記的檔批註的每個元素產生標識符字串。 此標識符字串會唯一識別來源專案。 檔查看器可以使用標識符字串來識別檔適用的對應專案。
檔檔不是原始程式碼的階層表示法;相反地,它是具有每個元素所產生標識符字串的一般清單。
D.4.2 識別符字串格式
檔案產生器會在產生識別元字串時觀察下列規則:
字串中未放置任何空白字元。
字串的第一個部分會透過單一字元後面接著冒號來識別所記載的成員種類。 定義下列型態的成員:
字元 說明 E 活動 F 欄位 月 方法(包括建構函式、完成項和運算子) 否 Namespace P 屬性 (包括索引器) T 類型 (例如類別、委派、列舉、介面和結構) ! 錯誤字串;字串的其餘部分會提供錯誤的相關信息。 例如,檔產生器會產生無法解析的連結錯誤資訊。 字串的第二個部分是專案的完整名稱,從命名空間的根目錄開始。 項目的名稱、其封入型別和命名空間會以句號分隔。 如果專案本身的名稱有句點,則會由 #(U+0023) 字元取代。 (假設沒有任何專案在其名稱中有這個字元。完整名稱中的類型自變數,當成員明確實作泛型介面的成員時,會藉由以 “
{
” 和 “” 字元取代它們周圍的 “<
” 和 “>
}
” 來編碼。對於具有自變數的方法和屬性,自變數清單會遵循括弧括住的自變數清單。 若為不含自變數的人,則會省略括弧。 引數會以逗號分隔。 每個自變數的編碼方式與 CLI 簽章相同,如下所示:
- 自變數會以檔名稱來表示,其依據其完整名稱修改如下:
- 代表泛型型別的自變數具有附加的 「
'
字元,後面接著類型參數的數目 - 具有、
out
或ref
修飾詞的in
自變數具有@
下列其類型名稱。 以值或透過params
傳遞的自變數沒有特殊表示法。 - 陣列的自變數會
[
以較低的系結:
大小,
表示...,
lowerbound:
大小]
其中逗號數目是較低的排名一,而每個維度的下限和大小,如果已知,則會以十進制表示。 如果未指定下限或大小,則會省略它。 如果省略特定維度的下限和大小,也會省略 “:
”。 Jagged 陣組會以每個層級一個 「[]
來表示」。 當下限為 0 時,單一維度陣列會省略下限 (預設值) (\17.1)。 - 具有以外的
void
指標型別的自變數,會使用*
下列類型名稱來表示。void
指標是使用的System.Void
型別名稱來表示。 - 參考類型上定義之泛型型別參數的自變數會使用 「
`
字元編碼,後面接著類型參數的以零起始的索引。 - 使用方法中定義的泛型型別參數的自變數會使用雙反引號 “
``
”,而不是用於型別的 “`
”。 - 參考建構泛型型別的自變數會使用泛型型別編碼,後面接著 “
{
”,後面接著以逗號分隔的類型自變數清單,後面接著 “}
”。
- 代表泛型型別的自變數具有附加的 「
- 自變數會以檔名稱來表示,其依據其完整名稱修改如下:
D.4.3 標識符字串範例
下列範例各顯示 C# 程式代碼片段,以及能夠有檔批注之每個來源元素所產生的識別符字串:
類型 會使用其完整名稱來表示,並使用泛型資訊來增強:
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_LogicalNot
op_UnaryNegation
、、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_Multiply
op_Modulus
op_BitwiseOr
op_Subtraction
op_Division
op_BitwiseAnd
、op_LeftShift
op_ExclusiveOr
op_Equality
op_RightShift
op_LessThanOrEqual
op_Inequality
op_LessThan
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"
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>
信息文字結尾。