Kommentarer till XML-dokumentation

C#-källfiler kan ha strukturerade kommentarer som skapar API-dokumentation för de typer som definieras i dessa filer. C#-kompilatorn skapar en XML-fil som innehåller strukturerade data som representerar kommentarer och API-signaturer. Andra verktyg kan bearbeta XML-utdata för att skapa dokumentation som kan läsas av människor i form av webbsidor eller PDF-filer, till exempel.

Den här processen ger dig många fördelar med att lägga till API-dokumentation i koden:

  • C#-kompilatorn kombinerar C#-kodens struktur med texten i kommentarerna i ett enda XML-dokument.
  • C#-kompilatorn verifierar att kommentarerna matchar API-signaturerna för relevanta taggar.
  • Verktyg som bearbetar XML-dokumentationsfilerna kan definiera XML-element och attribut som är specifika för dessa verktyg.

Verktyg som Visual Studio tillhandahåller IntelliSense för många vanliga XML-element som används i dokumentationskommenterar.

Den här artikeln beskriver följande ämnen:

  • Dokumentationskommentar och XML-filgenerering
  • Taggar som verifierats av C#-kompilatorn och Visual Studio
  • Format för den genererade XML-filen

Skapa XML-dokumentationsutdata

Du skapar dokumentation för koden genom att skriva särskilda kommentarsfält som anges med tre snedstreck. Kommentarsfälten innehåller XML-element som beskriver kodblocket som följer kommentarerna. Ett exempel:

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

Du anger antingen alternativet GenerateDocumentationFile eller DocumentationFile , så hittar kompilatorn alla kommentarsfält med XML-taggar i källkoden och skapar en XML-dokumentationsfil från dessa kommentarer. När det här alternativet är aktiverat genererar kompilatorn CS1591-varningen för alla offentligt synliga medlemmar som deklarerats i projektet utan kommentarer i XML-dokumentationen.

XML-kommentarsformat

Användningen av XML-dokumentkommentarer kräver avgränsare som anger var en dokumentationskommentar börjar och slutar. Du använder följande avgränsare med XML-dokumentationstaggar:

  • /// Avgränsare med en rad: Dokumentationsexemplen och C#-projektmallar använder det här formuläret. Om det finns tomt utrymme efter avgränsare ingår det inte i XML-utdata.

    Anteckning

    Visual Studio automatiskt infogar taggarna <summary> och </summary> och placerar markören i dessa taggar när du har skrivit /// avgränsaren i kodredigeraren. Du kan aktivera eller inaktivera den här funktionen i dialogrutan Alternativ.

  • /** */ Avgränsare med flera rader: Avgränsarna /** */ har följande formateringsregler:
    • Om resten av raden är tomt utrymme på raden som innehåller avgränsare bearbetas /** inte raden för kommentarer. Om det första tecknet efter /** avgränsare är tomt utrymme ignoreras det blankstegstecknet och resten av raden bearbetas. Annars bearbetas hela texten på raden efter /** avgränsare som en del av kommentaren.

    • Om det bara finns tomt utrymme upp till */ avgränsare på raden som innehåller */ avgränsare ignoreras den linjen. Annars bearbetas texten på raden upp till */ avgränsare som en del av kommentaren.

    • För raderna efter den som börjar med /** avgränsaren letar kompilatorn efter ett vanligt mönster i början av varje rad. Mönstret kan bestå av valfritt tomt utrymme och en asterisk (*), följt av fler valfria blanksteg. Om kompilatorn hittar ett vanligt mönster i början av varje rad som inte börjar med /** avgränsaren eller slutar med */ avgränsaren ignoreras det mönstret för varje rad.

    • Den enda delen av följande kommentar som bearbetas är raden som börjar med <summary>. De tre taggformaten ger samma kommentarer.

      /** <summary>text</summary> */
      
      /**
      <summary>text</summary>
      */
      
      /**
      * <summary>text</summary>
      */
      
    • Kompilatorn identifierar ett vanligt mönster för " * " i början av den andra och tredje raden. Mönstret ingår inte i utdata.

      /**
      * <summary>
      * text </summary>*/
      
    • Kompilatorn hittar inget vanligt mönster i följande kommentar eftersom det andra tecknet på den tredje raden inte är en asterisk. All text på den andra och tredje raden bearbetas som en del av kommentaren.

      /**
      * <summary>
         text </summary>
      */
      
    • Kompilatorn hittar inget mönster i följande kommentar av två skäl. För det första är antalet blanksteg före asterisken inte konsekvent. För det andra börjar den femte raden med en flik som inte matchar blanksteg. All text från raderna två till fem bearbetas som en del av kommentaren.

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

Om du vill referera till XML-element (till exempel dina funktioner bearbetar specifika XML-element som du vill beskriva i en XML-dokumentationskommentar) kan du använda standardmetoden för citat (&lt; och &gt;). Om du vill referera till allmänna identifierare i kodreferenselement (cref) kan du använda antingen escape-tecknen (till exempel cref="List&lt;T&gt;") eller klammerparenteser (cref="List{T}"). Som ett specialfall parsar kompilatorn klammerparenteserna som vinkelparenteser för att göra dokumentationskommentaren mindre besvärlig för författaren när den refererar till generiska identifierare.

Anteckning

XML-dokumentationens kommentarer är inte metadata. De ingår inte i den sammanställda sammansättningen och är därför inte tillgängliga genom reflektion.

Verktyg som accepterar XML-dokumentationsindata

Följande verktyg skapar utdata från XML-kommentarer:

  • DocFX: DocFX är en API-dokumentationsgenerator för .NET, som för närvarande stöder C#, Visual Basic och F#. Du kan också anpassa den genererade referensdokumentationen. DocFX skapar en statisk HTML-webbplats från källkoden och Markdown-filer. DocFX ger dig också flexibiliteten att anpassa webbplatsens layout och stil via mallar. Du kan också skapa anpassade mallar.
  • Sandcastle: Sandcastle-verktygen skapar hjälpfiler för hanterade klassbibliotek som innehåller både konceptuella och API-referenssidor. Sandcastle-verktygen är kommandoradsbaserade och har inga gui-klientdelar, projekthanteringsfunktioner eller automatiserad byggprocess. Sandcastle Help File Builder tillhandahåller fristående GUI och kommandoradsbaserade verktyg för att skapa en hjälpfil på ett automatiserat sätt. Ett Visual Studio integrationspaket är också tillgängligt för det så att hjälpprojekt kan skapas och hanteras helt inifrån Visual Studio.
  • Doxygen: Doxygen genererar en on-line-dokumentationswebbläsare (i HTML) eller en off-line referenshandbok (i LaTeX) från en uppsättning dokumenterade källfiler. Det finns också stöd för att generera utdata i RTF (MS Word), PostScript, hyperlänkad PDF, komprimerad HTML, DocBook och Unix man sidor. Du kan konfigurera Doxygen för att extrahera kodstrukturen från odokumenterade källfiler.

ID-strängar

Varje typ eller medlem lagras i ett element i XML-utdatafilen. Vart och ett av dessa element har en unik ID-sträng som identifierar typen eller medlemmen. ID-strängen måste ta hänsyn till operatorer, parametrar, returvärden, allmänna typparametrar, ref, inoch out parametrar. För att koda alla dessa potentiella element följer kompilatorn tydligt definierade regler för att generera ID-strängarna. Program som bearbetar XML-filen använder ID-strängen för att identifiera motsvarande .NET-metadata eller reflektionsobjekt som dokumentationen gäller för.

Kompilatorn observerar följande regler när den genererar ID-strängarna:

  • Inget tomt utrymme finns i strängen.

  • Den första delen av strängen identifierar typen av medlem med ett enda tecken följt av ett kolon. Följande medlemstyper används:

    Tecken Medlemstyp Kommentarer
    N namnområde Du kan inte lägga till dokumentationskommentare i ett namnområde, men du kan göra cref-referenser till dem, där det stöds.
    T typ En typ är en klass, ett gränssnitt, en struct, enum eller ett ombud.
    F fält
    P egenskap Innehåller indexerare eller andra indexerade egenskaper.
    M metod Innehåller särskilda metoder, till exempel konstruktorer och operatorer.
    E händelse
    ! felsträng Resten av strängen innehåller information om felet. C#-kompilatorn genererar felinformation för länkar som inte kan lösas.
  • Den andra delen av strängen är det fullständigt kvalificerade namnet på objektet, med början i namnområdets rot. Namnet på objektet, dess omslutande typer och namnområde avgränsas med punkter. Om namnet på själva objektet har punkter ersätts de av hash-tecknet ('#'). Det antas att inget objekt har en hash-sign direkt i sitt namn. Till exempel är det fullständigt kvalificerade namnet på strängkonstruktorn "System.String.#ctor".

  • För egenskaper och metoder följer parameterlistan inom parentes. Om det inte finns några parametrar finns inga parenteser. Parametrarna avgränsas med kommatecken. Kodningen för varje parameter följer direkt hur den kodas i en .NET-signatur (se Microsoft.VisualStudio.CorDebugInterop.CorElementType definitioner av alla caps-element i följande lista):

    • Bastyper. Vanliga typer (ELEMENT_TYPE_CLASS eller ELEMENT_TYPE_VALUETYPE) representeras som det fullständigt kvalificerade namnet på typen.
    • Inbyggda typer (till exempel ELEMENT_TYPE_I4, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRING, ELEMENT_TYPE_TYPEDBYREFoch ELEMENT_TYPE_VOID) representeras som det fullständigt kvalificerade namnet för motsvarande fullständiga typ. Exempel: System.Int32 eller System.TypedReference.
    • ELEMENT_TYPE_PTR representeras som en "*" efter den ändrade typen.
    • ELEMENT_TYPE_BYREF representeras som en "@" efter den ändrade typen.
    • ELEMENT_TYPE_CMOD_OPT representeras som ett '!' och det fullständigt kvalificerade namnet på modifierarklassen efter den ändrade typen.
    • ELEMENT_TYPE_SZARRAY representeras som "[]" efter matrisens elementtyp.
    • ELEMENT_TYPE_ARRAY representeras som [lowerbound:size,lowerbound:size] där antalet kommatecken är rangordningen - 1, och de lägre gränserna och storleken för varje dimension, om så är känt, representeras i decimaltal. Om en lägre gräns eller storlek inte anges utelämnas den. Om den lägre gränsen och storleken för en viss dimension utelämnas utelämnas även ":". En tvådimensionell matris med 1 som nedre gränser och ospecificerade storlekar är till exempel [1:,1:].
  • Endast för konverteringsoperatorer (op_Implicit och op_Explicit) kodas returvärdet för metoden som en ~ följt av returtypen. Till exempel: <member name="M:System.Decimal.op_Explicit(System.Decimal arg)~System.Int32"> är taggen för cast-operatorn public static explicit operator int (decimal value); som deklarerats System.Decimal i klassen .

  • För generiska typer följs namnet på typen av en backtick och sedan ett tal som anger antalet generiska typparametrar. Exempel: <member name="T:SampleClass``2"> är taggen för en typ som har definierats som public class SampleClass<T, U>. För metoder som tar generiska typer som parametrar anges de allmänna typparametrarna som siffror som föregås av backticks (till exempel "0",1). Varje tal representerar en nollbaserad matrisnotation för typens allmänna parametrar.

    • ELEMENT_TYPE_PINNED representeras som en ^efter den ändrade typen. C#-kompilatorn genererar aldrig den här kodningen.
    • ELEMENT_TYPE_CMOD_REQ representeras som en "|" och det fullständigt kvalificerade namnet på modifierarklassen efter den ändrade typen. C#-kompilatorn genererar aldrig den här kodningen.
    • ELEMENT_TYPE_GENERICARRAY representeras som "[?]" efter matrisens elementtyp. C#-kompilatorn genererar aldrig den här kodningen.
    • ELEMENT_TYPE_FNPTR representeras som "=FUNC:type(signature)", där type är returtypen och signaturen är argumenten för metoden. Om det inte finns några argument utelämnas parenteserna. C#-kompilatorn genererar aldrig den här kodningen.
    • Följande signaturkomponenter representeras inte eftersom de inte används för att särskilja överlagrade metoder:
      • samtalskonvention
      • returtyp
      • ELEMENT_TYPE_SENTINEL

I följande exempel visas hur ID-strängarna för en klass och dess medlemmar genereras:

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#-språkspecifikation

Mer information finns i C #-språkspecifikationsbilaga om dokumentationskommentare.