Opmerkingen bij XML-documentatie

C#-bronbestanden kunnen gestructureerde opmerkingen bevatten die API-documentatie produceren voor de typen die in die bestanden zijn gedefinieerd. De C#-compiler produceert een XML-bestand dat gestructureerde gegevens bevat die de opmerkingen en de API-handtekeningen vertegenwoordigen. Andere hulpprogramma's kunnen die XML-uitvoer verwerken om bijvoorbeeld leesbare documentatie te maken in de vorm van webpagina's of PDF-bestanden.

Dit proces biedt veel voordelen voor het toevoegen van API-documentatie in uw code:

  • De C#-compiler combineert de structuur van de C#-code met de tekst van de opmerkingen in één XML-document.
  • De C#-compiler controleert of de opmerkingen overeenkomen met de API-handtekeningen voor relevante tags.
  • Hulpprogramma's die de XML-documentatiebestanden verwerken, kunnen XML-elementen en kenmerken definiëren die specifiek zijn voor deze hulpprogramma's.

Hulpprogramma's zoals Visual Studio IntelliSense bieden voor veel algemene XML-elementen die worden gebruikt in documentatieopmerkingen.

In dit artikel worden de volgende onderwerpen behandeld:

  • Opmerkingen bij de documentatie en het genereren van XML-bestanden
  • Tags die zijn gevalideerd door de C#-compiler en Visual Studio
  • Indeling van het gegenereerde XML-bestand

XML-documentatie-uitvoer maken

U maakt documentatie voor uw code door speciale opmerkingsvelden te schrijven die worden aangegeven door drie schuine streepjes. De opmerkingenvelden bevatten XML-elementen die het codeblok beschrijven dat volgt op de opmerkingen. Bijvoorbeeld:

/// <summary>
///  This class performs an important function.
/// </summary>
public class MyClass {}

U stelt de optie GenerateDocumentationFile of DocumentationFile in en de compiler vindt alle opmerkingenvelden met XML-tags in de broncode en maakt een XML-documentatiebestand op basis van deze opmerkingen. Wanneer deze optie is ingeschakeld, genereert de compiler de cs1591-waarschuwing voor een openbaar zichtbaar lid dat in uw project is gedeclareerd zonder opmerkingen bij XML-documentatie.

XML-opmerkingenindelingen

Voor het gebruik van XML-documentopmerkingen zijn scheidingstekens vereist die aangeven waar een opmerking bij de documentatie begint en eindigt. U gebruikt de volgende scheidingstekens met de XML-documentatietags:

  • /// Scheidingsteken met één regel: de documentatievoorbeelden en C#-projectsjablonen gebruiken dit formulier. Als er witruimte is na het scheidingsteken, wordt deze niet opgenomen in de XML-uitvoer.

    Notitie

    Visual Studio de <summary> cursor automatisch invoegt en </summary> plaatst de cursor in deze tags nadat u het /// scheidingsteken in de code-editor hebt getypt. U kunt deze functie in- of uitschakelen in het dialoogvenster Opties.

  • /** */ Scheidingstekens met meerdere regels: De /** */ scheidingstekens hebben de volgende opmaakregels:
    • Als de rest van de regel witruimte is, wordt de regel niet verwerkt voor opmerkingen op de regel die het scheidingsteken bevat /** . Als het eerste teken na het /** scheidingsteken witruimte is, wordt dat witruimteteken genegeerd en wordt de rest van de regel verwerkt. Anders wordt de volledige tekst van de regel nadat het /** scheidingsteken is verwerkt als onderdeel van de opmerking.

    • Op de regel die het */ scheidingsteken bevat, wordt die regel genegeerd als er alleen witruimte tot het */ scheidingsteken is. Anders wordt de tekst op de regel tot aan het */ scheidingsteken verwerkt als onderdeel van de opmerking.

    • Voor de regels na de regel die begint met het /** scheidingsteken, zoekt de compiler naar een gemeenschappelijk patroon aan het begin van elke regel. Het patroon kan bestaan uit optionele witruimte en een sterretje (*), gevolgd door meer optionele witruimte. Als de compiler een gemeenschappelijk patroon vindt aan het begin van elke regel die niet begint met het /** scheidingsteken of eindigt met het */ scheidingsteken, wordt dat patroon voor elke regel genegeerd.

    • Het enige deel van de volgende opmerking die wordt verwerkt, is de regel die begint met <summary>. De drie tagindelingen produceren dezelfde opmerkingen.

      /** <summary>text</summary> */
      
      /**
      <summary>text</summary>
      */
      
      /**
      * <summary>text</summary>
      */
      
    • De compiler identificeert een gemeenschappelijk patroon van " * " aan het begin van de tweede en derde regel. Het patroon is niet opgenomen in de uitvoer.

      /**
      * <summary>
      * text </summary>*/
      
    • De compiler vindt geen gemeenschappelijk patroon in de volgende opmerking omdat het tweede teken op de derde regel geen sterretje is. Alle tekst op de tweede en derde regel wordt verwerkt als onderdeel van de opmerking.

      /**
      * <summary>
         text </summary>
      */
      
    • De compiler vindt om twee redenen geen patroon in de volgende opmerking. Ten eerste is het aantal spaties vóór het sterretje niet consistent. Ten tweede begint de vijfde regel met een tabblad, dat niet overeenkomt met spaties. Alle tekst van regels twee tot en met vijf wordt verwerkt als onderdeel van de opmerking.

      /**
        * <summary>
        * text
      *  text2
       	*  </summary>
      */
      

Als u wilt verwijzen naar XML-elementen (uw functie verwerkt bijvoorbeeld specifieke XML-elementen die u wilt beschrijven in een opmerking bij xml-documentatie), kunt u het standaardmechanisme voor quoteren (&lt; en &gt;) gebruiken. Als u naar algemene id's in codeverwijzingselementen (cref) wilt verwijzen, kunt u de escapetekens (bijvoorbeeld cref="List&lt;T&gt;") of accolades (cref="List{T}") gebruiken. Als een speciaal geval parseert de compiler de accolades als punthaken om de opmerking bij de documentatie minder lastig te maken voor auteur wanneer naar algemene id's wordt verwezen.

Notitie

De xml-documentatieopmerkingen zijn geen metagegevens; ze zijn niet opgenomen in de gecompileerde assembly en daarom zijn ze niet toegankelijk via reflectie.

Hulpprogramma's die XML-documentatieinvoer accepteren

Met de volgende hulpprogramma's maakt u uitvoer van XML-opmerkingen:

  • DocFX: DocFX is een API-documentatiegenerator voor .NET, die momenteel ondersteuning biedt voor C#, Visual Basic en F#. Hiermee kunt u ook de gegenereerde referentiedocumentatie aanpassen. DocFX bouwt een statische HTML-website op basis van uw broncode en Markdown-bestanden. DocFX biedt u ook de flexibiliteit om de indeling en stijl van uw website aan te passen via sjablonen. U kunt ook aangepaste sjablonen maken.
  • Sandcastle: De Sandcastle-hulpprogramma's maken Help-bestanden voor beheerde klassenbibliotheken die zowel conceptuele als API-referentiepagina's bevatten. De Sandcastle-hulpprogramma's zijn gebaseerd op opdrachtregels en hebben geen GUI-front-end, projectbeheerfuncties of geautomatiseerd buildproces. De Sandcastle Help File Builder biedt zelfstandige GUI- en opdrachtregelhulpprogramma's voor het bouwen van een Help-bestand op geautomatiseerde wijze. Er is ook een Visual Studio-integratiepakket beschikbaar, zodat helpprojecten volledig vanuit Visual Studio kunnen worden gemaakt en beheerd.
  • Doxygen: Doxygen genereert een online documentatiebrowser (in HTML) of een referentiehandleiding (in LaTeX) op basis van een set gedocumenteerde bronbestanden. Er is ook ondersteuning voor het genereren van uitvoer in RTF (MS Word), PostScript, hyperlinked PDF, gecomprimeerde HTML-, DocBook- en Unix-manpagina's. U kunt Doxygen zo configureren dat de codestructuur wordt geëxtraheerd uit niet-gedocumenteerde bronbestanden.

Id-tekenreeksen

Elk type of lid wordt opgeslagen in een element in het XML-uitvoerbestand. Elk van deze elementen heeft een unieke id-tekenreeks die het type of lid identificeert. De id-tekenreeks moet rekening houden met operators, parameters, retourwaarden, algemene typeparameters, refinen out parameters. Om al deze potentiële elementen te coderen, volgt de compiler duidelijk gedefinieerde regels voor het genereren van de id-tekenreeksen. Programma's die het XML-bestand verwerken, gebruiken de id-tekenreeks om de bijbehorende .NET-metagegevens of weerspiegelingsitem te identificeren waarop de documentatie van toepassing is.

De compiler observeert de volgende regels wanneer de id-tekenreeksen worden gegenereerd:

  • Er staat geen witruimte in de tekenreeks.

  • Het eerste deel van de tekenreeks identificeert het type lid met behulp van één teken gevolgd door een dubbele punt. De volgende lidtypen worden gebruikt:

    Teken Type lid Notities
    N naamruimte U kunt geen documentatieopmerkingen toevoegen aan een naamruimte, maar u kunt er crefverwijzingen naar maken, indien ondersteund.
    T type Een type is een klasse, interface, struct, opsomming of gemachtigde.
    F veld
    P property Bevat indexeerfuncties of andere geïndexeerde eigenschappen.
    M method Bevat speciale methoden, zoals constructors en operators.
    E Gebeurtenis
    ! fouttekenreeks De rest van de tekenreeks bevat informatie over de fout. De C#-compiler genereert foutinformatie voor koppelingen die niet kunnen worden opgelost.
  • Het tweede deel van de tekenreeks is de volledig gekwalificeerde naam van het item, te beginnen bij de hoofdmap van de naamruimte. De naam van het item, het bijbehorende type(en) en de naamruimte worden gescheiden door puntjes. Als de naam van het item zelf puntjes bevat, worden deze vervangen door het hash-teken ('#'). Er wordt ervan uitgegaan dat er geen item rechtstreeks een hash-teken in de naam heeft. De volledig gekwalificeerde naam van de tekenreeksconstructor is bijvoorbeeld System.String.#ctor.

  • Voor eigenschappen en methoden volgt de parameterlijst tussen haakjes. Als er geen parameters zijn, zijn er geen haakjes aanwezig. De parameters worden gescheiden door komma's. De codering van elke parameter volgt rechtstreeks hoe deze wordt gecodeerd in een .NET-handtekening (Zie Microsoft.VisualStudio.CorDebugInterop.CorElementType voor definities van alle hoofdletters in de volgende lijst):

    • Basistypen. Reguliere typen (ELEMENT_TYPE_CLASS of ELEMENT_TYPE_VALUETYPE) worden weergegeven als de volledig gekwalificeerde naam van het type.
    • Intrinsieke typen (bijvoorbeeld, ELEMENT_TYPE_I4ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRING, ELEMENT_TYPE_TYPEDBYREFen ELEMENT_TYPE_VOID) worden weergegeven als de volledig gekwalificeerde naam van het bijbehorende volledige type. Bijvoorbeeld System.Int32 of System.TypedReference.
    • ELEMENT_TYPE_PTR wordt weergegeven als een '*' na het gewijzigde type.
    • ELEMENT_TYPE_BYREF wordt weergegeven als een @na het gewijzigde type.
    • ELEMENT_TYPE_CMOD_OPT wordt weergegeven als een '!' en de volledig gekwalificeerde naam van de modifier-klasse, gevolgd door het gewijzigde type.
    • ELEMENT_TYPE_SZARRAY wordt weergegeven als '[]' na het elementtype van de matrix.
    • ELEMENT_TYPE_ARRAY wordt weergegeven als [lowerbound:size,lowerbound:size] waarbij het aantal komma's de rang - 1 is en de ondergrenzen en grootte van elke dimensie, indien bekend, worden weergegeven in decimaal. Als er geen ondergrens of grootte is opgegeven, wordt deze weggelaten. Als de ondergrens en grootte voor een bepaalde dimensie worden weggelaten, wordt ook de ':' weggelaten. Een tweedimensionale matrix met 1 als ondergrens en niet-opgegeven grootte is bijvoorbeeld [1:,1:].
  • Alleen voor conversieoperators (op_Implicit en op_Explicit) wordt de retourwaarde van de methode gecodeerd als een ~ gevolgd door het retourtype. Bijvoorbeeld: <member name="M:System.Decimal.op_Explicit(System.Decimal arg)~System.Int32"> is de tag voor de cast-operator public static explicit operator int (decimal value); die is gedeclareerd in de System.Decimal klasse.

  • Voor algemene typen wordt de naam van het type gevolgd door een backtick en vervolgens een getal dat het aantal algemene typeparameters aangeeft. Bijvoorbeeld: <member name="T:SampleClass``2"> is de tag voor een type dat is gedefinieerd als public class SampleClass<T, U>. Voor methoden die algemene typen als parameters gebruiken, worden de algemene typeparameters opgegeven als getallen voorafgegaan door backticks (bijvoorbeeld '0,'1). Elk getal vertegenwoordigt een matrixnotatie op basis van nul voor de algemene parameters van het type.

    • ELEMENT_TYPE_PINNED wordt weergegeven als ^na het gewijzigde type. De C#-compiler genereert deze codering nooit.
    • ELEMENT_TYPE_CMOD_REQ wordt weergegeven als een '|' en de volledig gekwalificeerde naam van de modifier-klasse, gevolgd door het gewijzigde type. De C#-compiler genereert deze codering nooit.
    • ELEMENT_TYPE_GENERICARRAY wordt weergegeven als [?], na het elementtype van de matrix. De C#-compiler genereert deze codering nooit.
    • ELEMENT_TYPE_FNPTR wordt weergegeven als '=FUNC:type(signature)', waarbij type het retourtype is en de handtekening de argumenten van de methode is. Als er geen argumenten zijn, worden de haakjes weggelaten. De C#-compiler genereert deze codering nooit.
    • De volgende handtekeningonderdelen worden niet weergegeven omdat ze niet worden gebruikt om overbelaste methoden te onderscheiden:
      • oproepconventie
      • retourtype
      • ELEMENT_TYPE_SENTINEL

In de volgende voorbeelden ziet u hoe de id-tekenreeksen voor een klasse en de bijbehorende leden worden gegenereerd:

namespace MyNamespace
{
    /// <summary>
    /// Enter description here for class X.
    /// ID string generated is "T:MyNamespace.MyClass".
    /// </summary>
    public unsafe class MyClass
    {
        /// <summary>
        /// Enter description here for the first constructor.
        /// ID string generated is "M:MyNamespace.MyClass.#ctor".
        /// </summary>
        public MyClass() { }

        /// <summary>
        /// Enter description here for the second constructor.
        /// ID string generated is "M:MyNamespace.MyClass.#ctor(System.Int32)".
        /// </summary>
        /// <param name="i">Describe parameter.</param>
        public MyClass(int i) { }

        /// <summary>
        /// Enter description here for field message.
        /// ID string generated is "F:MyNamespace.MyClass.message".
        /// </summary>
        public string? message;

        /// <summary>
        /// Enter description for constant PI.
        /// ID string generated is "F:MyNamespace.MyClass.PI".
        /// </summary>
        public const double PI = 3.14;

        /// <summary>
        /// Enter description for method func.
        /// ID string generated is "M:MyNamespace.MyClass.func".
        /// </summary>
        /// <returns>Describe return value.</returns>
        public int func() { return 1; }

        /// <summary>
        /// Enter description for method someMethod.
        /// ID string generated is "M:MyNamespace.MyClass.someMethod(System.String,System.Int32@,System.Void*)".
        /// </summary>
        /// <param name="str">Describe parameter.</param>
        /// <param name="num">Describe parameter.</param>
        /// <param name="ptr">Describe parameter.</param>
        /// <returns>Describe return value.</returns>
        public int someMethod(string str, ref int nm, void* ptr) { return 1; }

        /// <summary>
        /// Enter description for method anotherMethod.
        /// ID string generated is "M:MyNamespace.MyClass.anotherMethod(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 anotherMethod(short[] array1, int[,] array) { return 0; }

        /// <summary>
        /// Enter description for operator.
        /// ID string generated is "M:MyNamespace.MyClass.op_Addition(MyNamespace.MyClass,MyNamespace.MyClass)".
        /// </summary>
        /// <param name="first">Describe parameter.</param>
        /// <param name="second">Describe parameter.</param>
        /// <returns>Describe return value.</returns>
        public static MyClass operator +(MyClass first, MyClass second) { return first; }

        /// <summary>
        /// Enter description for property.
        /// ID string generated is "P:MyNamespace.MyClass.prop".
        /// </summary>
        public int prop { get { return 1; } set { } }

        /// <summary>
        /// Enter description for event.
        /// ID string generated is "E:MyNamespace.MyClass.OnHappened".
        /// </summary>
        public event Del? OnHappened;

        /// <summary>
        /// Enter description for index.
        /// ID string generated is "P:MyNamespace.MyClass.Item(System.String)".
        /// </summary>
        /// <param name="str">Describe parameter.</param>
        /// <returns></returns>
        public int this[string s] { get { return 1; } }

        /// <summary>
        /// Enter description for class Nested.
        /// ID string generated is "T:MyNamespace.MyClass.Nested".
        /// </summary>
        public class Nested { }

        /// <summary>
        /// Enter description for delegate.
        /// ID string generated is "T:MyNamespace.MyClass.Del".
        /// </summary>
        /// <param name="i">Describe parameter.</param>
        public delegate void Del(int i);

        /// <summary>
        /// Enter description for operator.
        /// ID string generated is "M:MyNamespace.MyClass.op_Explicit(MyNamespace.MyClass)~System.Int32".
        /// </summary>
        /// <param name="myParameter">Describe parameter.</param>
        /// <returns>Describe return value.</returns>
        public static explicit operator int(MyClass myParameter) { return 1; }
    }
}

C#-taalspecificatie

Zie de bijlage C#-taalspecificatie voor documentatieopmerkingen voor meer informatie.