Delen via


Opmerkingen bij xml-API-documentatie genereren

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 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 waarmee de XML-documentatiebestanden worden verwerkt, kunnen XML-elementen en -kenmerken definiëren die specifiek zijn voor deze hulpprogramma's.

Hulpprogramma's zoals Visual Studio bieden IntelliSense 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 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 opmerkingvelden te schrijven die worden aangegeven door drievoudige slashes. De opmerkingenvelden bevatten XML-elementen die het codeblok beschrijven dat de opmerkingen volgt. Voorbeeld:

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

U stelt de optie GenerateDocumentationFile of DocumentationFile in en de compiler vindt alle opmerkingvelden 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 in 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 witruimte het scheidingsteken volgt, wordt deze niet opgenomen in de XML-uitvoer.

    Opmerking

    Visual Studio voegt de <summary> cursor automatisch in 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 spatieteken genegeerd en wordt de rest van de regel verwerkt. Anders wordt de hele tekst van de regel na het /** scheidingsteken verwerkt als onderdeel van de opmerking.

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

    • Voor de regels na het scheidingsteken dat 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/of 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 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 quotatie (&lt; en &gt;). 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. In een speciaal geval parseert de compiler de accolades als hoekhaken om de documentatie minder omslachtig te maken voor de auteur bij het verwijzen naar algemene id's.

Opmerking

Als u opmerkingen schrijft met behulp van het scheidingsteken voor XML-opmerkingen met één regel, ///maar geen tags bevat, voegt de compiler de tekst van deze opmerkingen toe aan het XML-uitvoerbestand. De uitvoer bevat echter geen XML-elementen zoals <summary>. De meeste hulpprogramma's die XML-opmerkingen gebruiken (inclusief Visual Studio IntelliSense) lezen deze opmerkingen niet.

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 klassebibliotheken 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 een geautomatiseerde manier. Er is ook een Visual Studio-integratiepakket beschikbaar, zodat helpprojecten volledig vanuit Visual Studio kunnen worden gemaakt en beheerd.
  • Doxygen: Doxygen genereert een onlinedocumentatiebrowser (in HTML) of een offline referentiehandleiding (in LaTeX) 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-handmatige pagina's. U kunt Doxygen configureren om de codestructuur uit niet-gedocumenteerde bronbestanden te extraheren.

Opmerking

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

Id-tekenreeksen

Elk type of lid wordt opgeslagen in een element in het XML-uitvoerbestand. Elk van deze elementen heeft een unieke id-tekenreeks waarmee het type of lid wordt geïdentificeerd. De id-tekenreeks moet rekening houden met operators, parameters, retourwaarden, algemene typeparameters, refinen out parameters. Om al deze mogelijke 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 ziet de volgende regels wanneer de id-tekenreeksen worden gegenereerd:

  • Er is geen witruimte in de tekenreeks.

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

    Karakter Ledentype Opmerkingen
    N naamruimte U kunt geen documentatieopmerkingen toevoegen aan een naamruimte, maar u kunt cref verwijzingen naar deze maken, waar ondersteund.
    T soort Een type is een klasse, interface, struct, opsomming of gemachtigde.
    F veld
    P vastgoed Bevat indexeerfuncties of andere geïndexeerde eigenschappen.
    M methode 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 punten bevat, worden deze vervangen door het hash-teken ('#'). In de grammatica wordt ervan uitgegaan dat er geen item rechtstreeks een hash-aanmelding heeft in de naam. 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_I4, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRING, ELEMENT_TYPE_TYPEDBYREFen ELEMENT_TYPE_VOID) worden weergegeven als de volledig gekwalificeerde naam van het bijbehorende volledige type. Een voorbeeld hiervan is 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 wijzigingsklasse, na het gewijzigde type.
    • ELEMENT_TYPE_SZARRAY wordt weergegeven als '[]' na het elementtype van de matrix.
    • ELEMENT_TYPE_ARRAY wordt weergegeven als [ondergrens:size,ondergrens:size] waarbij het aantal komma's de rang - 1 is, en de ondergrenzen en grootte van elke dimensie, indien bekend, worden weergegeven in decimaal. De ondergrens en grootte worden weggelaten als ze niet zijn opgegeven. Als de ondergrens en grootte voor een bepaalde dimensie worden weggelaten, wordt de ':' ook weggelaten. Een tweedimensionale matrix met 1 als ondergrens en niet-opgegeven grootte is bijvoorbeeld [1:,1:].
  • Voor alleen 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 in de System.Decimal klasse is gedeclareerd.

  • 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, na 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(handtekening)", 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() => 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 num, 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] => 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) => 1;
}

C#-taalspecificatie

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