處理 XML 檔案 (C# 程式設計手冊)
編譯器會為每一個加上標記的程式碼的建構產生一個 ID 字串,用來產生文件 (如需將程式碼加上標記的詳細資訊,請參閱建議的文件註解標記)。ID 字串會將建構獨一無二地識別出來。 處理 XML 檔案的程式可以使用 ID 字串來識別文件也適用之 .NET Framework 中對應的中繼資料/反映項目。
XML 檔案並不是程式碼的階層架構表示,它是一個平面圖式的清單,其中每個項目都有一個 ID。
在產生 ID 字串時,編譯器會遵守下列的規則:
字串中不能有空白。
ID 字串的第一個部分 (單一字元後接著一個分號) 識別了成員的種類。 下面是使用的成員型別:
字元
描述
N
命名空間
您不能將文件註解加入命名空間裡,但是可以讓 cref 參考這些文件註解 (如果有支援這項功能)
T
型別:類別、介面、結構、列舉、委派
F
欄位
P
屬性 (包括索引工具或其他索引屬性)
M
方法 (包括如建構函式、運算子等特別的方法)
E
事件
!
錯誤字串
字串的其餘部分會提供該錯誤的相關資訊。 C# 編譯器對於無法解析的連結會產生錯誤資訊
字串的第二個部分是該項目的完整名稱 (開始於命名空間的根)。 該項目的名稱、它的封入型別以及命名空間由句號分開。 若該項目的名稱本身含有句號,則句號會被井字號 (#) 所替換。 一般假設在項目名稱中不會直接出現井字號 (#)。 例如,字串建構函式的完整名稱為 "System.String.#ctor"。
對於屬性和方法,若方法有引數,則後面會接著由括號括起來的引數清單。 如果沒有引數,就不會有括弧出現。 引數間是以逗號來分隔。 每個引數的編碼直接遵照 .NET Framework 簽章中的編碼方式:
基底型別。 標準型別 (ELEMENT_TYPE_CLASS 或 ELEMENT_TYPE_VALUETYPE) 以該型別的完整名稱表示。
內建型別 (例如,ELEMENT_TYPE_I4、ELEMENT_TYPE_OBJECT、ELEMENT_TYPE_STRING、ELEMENT_TYPE_TYPEDBYREF。 和 ELEMENT_TYPE_VOID) 表示為對應之完整型別的完整名稱。 例如,System.Int32 或 System.TypedReference。
ELEMENT_TYPE_PTR 於修改的型別後以 '*' 表示。
ELEMENT_TYPE_BYREF 於修改的型別後以 '@' 表示。
ELEMENT_TYPE_PINNED 於修改的型別後以 '^' 表示。 C# 編譯器永遠不會產生這個。
ELEMENT_TYPE_CMOD_REQ 於修改的型別後以 '|' 和修飾詞類別的完整名稱表示。 C# 編譯器永遠不會產生這個。
ELEMENT_TYPE_CMOD_OPT 於修改的型別後以 '!' 和修飾詞類別的完整名稱表示。
ELEMENT_TYPE_SZARRAY 在陣列的項目型別後以 "[]" 表示。
ELEMENT_TYPE_GENERICARRAY 在陣列的項目型別後以 "[?]" 表示。 C# 編譯器永遠不會產生這個。
ELEMENT_TYPE_ARRAY 以 [lowerbound:size,lowerbound:size] 表示,其中逗號的數目為陣序規範 -1,若已知每個維度的下限與大小,則以十進位表示。 若沒有指定下限或大小,則會被忽略。 若省略了特定維度的下限及大小,則 ":" 也會被省略。 例如,一個沒有指定大小的二維陣列的下限是 1,則會以 [1:,1:] 表示。
ELEMENT_TYPE_FNPTR 以「=FUNC:type(signature)」表示,其中 type 為傳回型別,而 signature 為方法的引數。 如果沒有引數的話,就會省略括弧。 C# 編譯器永遠不會產生這個。
將不顯示下列的簽章元件,因為它們從不用來區分多載的方法。
呼叫慣例
傳回型別
ELEMENT_TYPE_SENTINEL
方法的傳回值僅會對轉換運算子 (op_Implicit 和 op_Explicit) 編碼成 '~' 後面接傳回型別,如同上述的編碼一樣。
泛型型別的名稱後面會有一個反勾號,然後是表示泛型型別參數數目的數字。 例如:
<member name="T:SampleClass`2"> 是定義為 public class SampleClass<T, U> 之型別的標記。
若為使用泛型型別做為參數的方法,會將泛型型別參數指定為前面加上反勾號的數字 (例如 `0、`1)。 每個數字都代表型別泛型參數以零起始的陣列。
範例
下面的範例說明了類別與其成員的 ID 字串如何產生:
namespace N
{
/// <summary>
/// Enter description here for class X.
/// ID string generated is "T:N.X".
/// </summary>
public unsafe class X
{
/// <summary>
/// Enter description here for the first constructor.
/// ID string generated is "M:N.X.#ctor".
/// </summary>
public X() { }
/// <summary>
/// Enter description here for the second constructor.
/// ID string generated is "M:N.X.#ctor(System.Int32)".
/// </summary>
/// <param name="i">Describe parameter.</param>
public X(int i) { }
/// <summary>
/// Enter description here for field q.
/// ID string generated is "F:N.X.q".
/// </summary>
public string q;
/// <summary>
/// Enter description for constant PI.
/// ID string generated is "F:N.X.PI".
/// </summary>
public const double PI = 3.14;
/// <summary>
/// Enter description for method f.
/// ID string generated is "M:N.X.f".
/// </summary>
/// <returns>Describe return value.</returns>
public int f() { return 1; }
/// <summary>
/// Enter description for method bb.
/// ID string generated is "M:N.X.bb(System.String,System.Int32@,System.Void*)".
/// </summary>
/// <param name="s">Describe parameter.</param>
/// <param name="y">Describe parameter.</param>
/// <param name="z">Describe parameter.</param>
/// <returns>Describe return value.</returns>
public int bb(string s, ref int y, void* z) { return 1; }
/// <summary>
/// Enter description for method gg.
/// ID string generated is "M:N.X.gg(System.Int16[],System.Int32[0:,0:])".
/// </summary>
/// <param name="array1">Describe parameter.</param>
/// <param name="array">Describe parameter.</param>
/// <returns>Describe return value.</returns>
public int gg(short[] array1, int[,] array) { return 0; }
/// <summary>
/// Enter description for operator.
/// ID string generated is "M:N.X.op_Addition(N.X,N.X)".
/// </summary>
/// <param name="x">Describe parameter.</param>
/// <param name="xx">Describe parameter.</param>
/// <returns>Describe return value.</returns>
public static X operator +(X x, X xx) { return x; }
/// <summary>
/// Enter description for property.
/// ID string generated is "P:N.X.prop".
/// </summary>
public int prop { get { return 1; } set { } }
/// <summary>
/// Enter description for event.
/// ID string generated is "E:N.X.d".
/// </summary>
public event D d;
/// <summary>
/// Enter description for property.
/// ID string generated is "P:N.X.Item(System.String)".
/// </summary>
/// <param name="s">Describe parameter.</param>
/// <returns></returns>
public int this[string s] { get { return 1; } }
/// <summary>
/// Enter description for class Nested.
/// ID string generated is "T:N.X.Nested".
/// </summary>
public class Nested { }
/// <summary>
/// Enter description for delegate.
/// ID string generated is "T:N.X.D".
/// </summary>
/// <param name="i">Describe parameter.</param>
public delegate void D(int i);
/// <summary>
/// Enter description for operator.
/// ID string generated is "M:N.X.op_Explicit(N.X)~System.Int32".
/// </summary>
/// <param name="x">Describe parameter.</param>
/// <returns>Describe return value.</returns>
public static explicit operator int(X x) { return 1; }
}
}