Przetwarzanie plików dokumentacji XML
Kompilator generuje ciąg identyfikatora dla każdej konstrukcji w kodzie oznaczonym tagiem w celu wygenerowania dokumentacji. Aby uzyskać więcej informacji, zobacz Zalecane tagi komentarze dokumentacji. Ciąg identyfikatora jednoznacznie identyfikuje konstrukcję. Programy, które przetwarzają plik XML, mogą używać ciągu identyfikatora do identyfikowania odpowiednich metadanych programu .NET Framework lub elementu odbicia, do którego ma zastosowanie dokumentacja.
Plik XML nie jest hierarchiczną reprezentacją kodu, jest to płaska lista z wygenerowanym identyfikatorem dla każdego elementu.
Kompilator obserwuje następujące reguły podczas generowania ciągów identyfikatorów:
W ciągu nie jest umieszczana biała spacja.
Pierwsza część ciągu identyfikatora identyfikuje rodzaj identyfikowanego elementu członkowskiego z pojedynczym znakiem, po którym następuje dwukropek. Używane są następujące typy składowych:
Znak opis N Przestrzeń nazw
Nie można dodawać komentarzy dokumentacji do przestrzeni nazw. Możliwe są odwołania cref do przestrzeni nazw.T Typ: klasa, interfejs, struktura, wyliczenie, delegat D Definicja typu F Pole P Właściwość (w tym indeksatory lub inne właściwości indeksowane) M Metoda (w tym takie specjalne metody jak konstruktory, operatory itd.) E Zdarzenie ! Ciąg błędu
Pozostała część ciągu zawiera informacje o błędzie. Kompilator MSVC generuje informacje o błędach dla linków, których nie można rozpoznać.Druga część ciągu jest w pełni kwalifikowaną nazwą elementu, zaczynając od katalogu głównego przestrzeni nazw. Nazwa elementu, jego otaczającego typu lub typów, a przestrzeń nazw jest oddzielona kropkami. Jeśli nazwa samego elementu zawiera kropki, są one zastępowane znakiem skrótu ('#'). Zakłada się, że żaden element nie ma znaku skrótu bezpośrednio w nazwie. Na przykład w pełni kwalifikowana nazwa konstruktora
String
toSystem.String.#ctor
.W przypadku właściwości i metod, jeśli istnieją argumenty do metody, lista argumentów ujęta w nawiasy następuje. Jeśli nie ma żadnych argumentów, nie ma nawiasów. Argumenty są oddzielone przecinkami. Każdy argument jest kodowany w taki sam sposób, jak kodowany w podpisie programu .NET Framework:
Typy podstawowe. Typy regularne (
ELEMENT_TYPE_CLASS
lubELEMENT_TYPE_VALUETYPE
) są reprezentowane jako w pełni kwalifikowana nazwa typu.Typy wewnętrzne (na przykład
ELEMENT_TYPE_I4
, ,ELEMENT_TYPE_OBJECT
ELEMENT_TYPE_STRING
,ELEMENT_TYPE_TYPEDBYREF
iELEMENT_TYPE_VOID
) są reprezentowane jako w pełni kwalifikowana nazwa odpowiadającego mu pełnego typu, na przykładSystem.Int32
lubSystem.TypedReference
.ELEMENT_TYPE_PTR
element jest reprezentowany jako "*
" po zmodyfikowanym typie.ELEMENT_TYPE_BYREF
element jest reprezentowany jako "@
" po zmodyfikowanym typie.ELEMENT_TYPE_PINNED
element jest reprezentowany jako "^
" po zmodyfikowanym typie. Kompilator MSVC nigdy nie generuje tego elementu.ELEMENT_TYPE_CMOD_REQ
element jest reprezentowany jako "|
" i w pełni kwalifikowana nazwa klasy modyfikatora, po zmodyfikowanym typie. Kompilator MSVC nigdy nie generuje tego elementu.ELEMENT_TYPE_CMOD_OPT
element jest reprezentowany jako "!
" i w pełni kwalifikowana nazwa klasy modyfikatora, po zmodyfikowanym typie.ELEMENT_TYPE_SZARRAY
jest reprezentowany jako "[]
" po typie elementu tablicy.ELEMENT_TYPE_GENERICARRAY
jest reprezentowany jako "[?]
" po typie elementu tablicy. Kompilator MSVC nigdy nie generuje tego elementu.ELEMENT_TYPE_ARRAY
jest reprezentowany jako[
mniejszy rozmiar ograniczenia o niższym rozmiarze,
]
granic:
:
, gdzie liczba przecinków jest rangą - 1, a dolna granica i rozmiar każdego wymiaru, jeśli jest znany, są reprezentowane w przecinku. Jeśli nie określono mniejszej granicy lub rozmiaru, zostanie pominięty. Jeśli dolna granica i rozmiar zostaną pominięte dla określonego wymiaru, parametr ":
" również zostanie pominięty. Na przykład tablica 2-wymiarowa z 1 jako dolna granica i nieokreślone rozmiary są reprezentowane jako[1:,1:]
.ELEMENT_TYPE_FNPTR
element jest reprezentowany jako "=FUNC:(type
signature)", gdzietype
jest typem zwrotnym, a podpis jest argumentami metody . Jeśli nie ma argumentów, nawiasy zostaną pominięte. Kompilator MSVC nigdy nie generuje tego elementu.
Następujące składniki podpisu nie są reprezentowane, ponieważ nigdy nie są używane do różnicowania przeciążonych metod:
Konwencja wywoływania
Typ zwracany
ELEMENT_TYPE_SENTINEL
Tylko w przypadku operatorów konwersji wartość zwracana metody jest kodowana jako "
~
", a następnie zwracany typ, zgodnie z wcześniejszym kodowaniem.W przypadku typów ogólnych nazwa typu będzie następuje znacznik wsteczny, a następnie liczba wskazująca liczbę parametrów typu ogólnego. Przykład:
<member name="T:MyClass`2">
W przykładzie pokazano typ zdefiniowany jako
public class MyClass<T, U>
.W przypadku metod, które przyjmują typy ogólne jako parametry, parametry typu ogólnego są określane jako liczby poprzedzone znacznikami wstecznymi (na przykład "0", "1"). Każda liczba reprezentuje położenie tablicy opartej na zera dla parametrów ogólnych typu.
Przykład
W poniższych przykładach pokazano, jak są generowane ciągi identyfikatorów klasy i jej składowych.
// xml_id_strings.cpp
// compile with: /clr /doc /LD
///
namespace N {
// "N:N"
/// <see cref="System" />
// <see cref="N:System"/>
ref class X {
// "T:N.X"
protected:
///
!X(){}
// "M:N.X.Finalize", destructor's representation in metadata
public:
///
X() {}
// "M:N.X.#ctor"
///
static X() {}
// "M:N.X.#cctor"
///
X(int i) {}
// "M:N.X.#ctor(System.Int32)"
///
~X() {}
// "M:N.X.Dispose", Dispose function representation in metadata
///
System::String^ q;
// "F:N.X.q"
///
double PI;
// "F:N.X.PI"
///
int f() { return 1; }
// "M:N.X.f"
///
int bb(System::String ^ s, int % y, void * z) { return 1; }
// "M:N.X.bb(System.String,System.Int32@,System.Void*)"
///
int gg(array<short> ^ array1, array< int, 2 >^ IntArray) { return 0; }
// "M:N.X.gg(System.Int16[], System.Int32[0:,0:])"
///
static X^ operator+(X^ x, X^ xx) { return x; }
// "M:N.X.op_Addition(N.X,N.X)"
///
property int prop;
// "M:N.X.prop"
///
property int prop2 {
// "P:N.X.prop2"
///
int get() { return 0; }
// M:N.X.get_prop2
///
void set(int i) {}
// M:N.X.set_prop2(System.Int32)
}
///
delegate void D(int i);
// "T:N.X.D"
///
event D ^ d;
// "E:N.X.d"
///
ref class Nested {};
// "T:N.X.Nested"
///
static explicit operator System::Int32 (X x) { return 1; }
// "M:N.X.op_Explicit(N.X!System.Runtime.CompilerServices.IsByValue)~System.Int32"
};
}