Compartilhar via


Gerar comentários da documentação da API XML

Os arquivos de origem do C# podem incluir comentários estruturados que produzem a documentação da API para os tipos definidos nesses arquivos. O compilador C# produz um arquivo XML que contém dados estruturados que representam os comentários e as assinaturas da API. Outras ferramentas podem processar essa saída XML para criar documentação legível por humanos na forma de páginas da Web ou arquivos PDF, por exemplo.

Esse processo oferece muitas vantagens para você adicionar a documentação da API em seu código:

  • O compilador C# combina a estrutura do código C# com o texto dos comentários em um único documento XML.
  • O compilador C# verifica se os comentários correspondem às assinaturas da API para marcas relevantes.
  • As ferramentas que processam os arquivos de documentação XML podem definir elementos XML e atributos específicos a essas ferramentas.

Ferramentas como o Visual Studio fornecem o IntelliSense para muitos elementos XML comuns usados em comentários de documentação.

Este artigo aborda estes tópicos:

  • Comentários de documentação e geração de arquivos XML
  • Marcas validadas pelo compilador C# e pelo Visual Studio
  • Formato do arquivo XML gerado

Criar saída da documentação XML

Crie documentação para seu código escrevendo campos de comentário especiais indicados por barras triplas. Os campos de comentário incluem elementos XML que descrevem o bloco de código que segue os comentários. Por exemplo:

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

Você define a opção GenerateDocumentationFile ou DocumentationFile e o compilador localiza todos os campos de comentário com marcas XML no código-fonte e cria um arquivo de documentação XML com base nesses comentários. Quando essa opção está habilitada, o compilador gera o aviso CS1591 para qualquer membro publicamente visível declarado em seu projeto sem comentários de documentação XML.

Formatos de comentário XML

O uso de comentários de documento XML requer delimitadores que indicam onde um comentário de documentação começa e termina. Use os seguintes delimitadores com as marcas de documentação XML:

  • /// Delimitador de linha única: os exemplos de documentação e os modelos de projeto em C# usam esse formulário. Se o espaço em branco seguir o delimitador, ele não será incluído na saída XML.

    Observação

    O Visual Studio insere automaticamente as <summary> marcas e </summary> posiciona o cursor dentro dessas marcas depois de digitar o /// delimitador no editor de código. Você pode ativar ou desativar esse recurso na caixa de diálogo Opções.

  • /** */ Delimitadores multilinha: os /** */ delimitadores têm as seguintes regras de formatação:
    • Na linha que contém o /** delimitador, se o restante da linha for espaço em branco, a linha não será processada para comentários. Se o primeiro caractere após o /** delimitador for espaço em branco, esse caractere de espaço em branco será ignorado e o restante da linha será processado. Caso contrário, todo o texto da linha após o /** delimitador é processado como parte do comentário.

    • Na linha que contém o */ delimitador, se houver apenas espaço em branco até o */ delimitador, essa linha será ignorada. Caso contrário, o texto na linha até o */ delimitador será processado como parte do comentário.

    • Para as linhas após a que começa com o /** delimitador, o compilador procura um padrão comum no início de cada linha. O padrão pode consistir em espaço em branco opcional e/ou um asterisco (*), seguido por mais espaço em branco opcional. Se o compilador encontrar um padrão comum no início de cada linha que não comece com o /** delimitador ou termine com o */ delimitador, ele ignorará esse padrão para cada linha.

    • A única parte do comentário a seguir processado é a linha que começa com <summary>. Os três formatos de marca produzem os mesmos comentários.

      /** <summary>text</summary> */
      
      /**
      <summary>text</summary>
      */
      
      /**
      * <summary>text</summary>
      */
      
    • O compilador identifica um padrão comum de " * " no início da segunda e terceira linhas. O padrão não está incluído na saída.

      /**
      * <summary>
      * text </summary>*/
      
    • O compilador não encontra nenhum padrão comum no comentário a seguir porque o segundo caractere na terceira linha não é um asterisco. Todo o texto na segunda e terceira linhas é processado como parte do comentário.

      /**
      * <summary>
         text </summary>
      */
      
    • O compilador não encontra nenhum padrão no comentário a seguir por dois motivos. Primeiro, o número de espaços antes do asterisco não é consistente. Em segundo lugar, a quinta linha começa com uma guia, que não corresponde a espaços. Todo o texto das linhas dois a cinco é processado como parte do comentário.

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

Para se referir a elementos XML (por exemplo, sua função processa elementos XML específicos que você deseja descrever em um comentário de documentação XML), você pode usar o mecanismo de aspas padrão (&lt; e &gt;). Para se referir a identificadores genéricos em elementos de referência de código (cref), você pode usar os caracteres de escape (por exemplo) cref="List&lt;T&gt;"ou chaves (cref="List{T}"). Como um caso especial, o compilador analisa as chaves como colchetes angulares para tornar o comentário da documentação menos complicado para o autor ao se referir a identificadores genéricos.

Observação

Se você escrever comentários usando o delimitador de comentário XML de linha única, ///mas não incluir marcas, o compilador adicionará o texto desses comentários ao arquivo de saída XML. No entanto, a saída não inclui elementos XML, como <summary>. A maioria das ferramentas que consomem comentários XML (incluindo o Visual Studio IntelliSense) não lê esses comentários.

Ferramentas que aceitam a entrada da documentação XML

As seguintes ferramentas criam saída com base em comentários XML:

  • DocFX: DocFX é um gerador de documentação de API para .NET, que atualmente dá suporte a C#, Visual Basic e F#. Ele também permite personalizar a documentação de referência gerada. O DocFX cria um site HTML estático com base no código-fonte e nos arquivos Markdown. Além disso, o DocFX oferece a flexibilidade para personalizar o layout e o estilo do seu site por meio de modelos. Você também pode criar modelos personalizados.
  • Sandcastle: as ferramentas do Sandcastle criam arquivos de ajuda para bibliotecas de classes gerenciadas que contêm páginas de referência conceituais e de API. As ferramentas do Sandcastle são baseadas em linha de comando e não têm nenhum front-end de GUI, recursos de gerenciamento de projetos ou processo de build automatizado. O Construtor de Arquivos de Ajuda do Sandcastle fornece gui autônomo e ferramentas baseadas em linha de comando para criar um arquivo de ajuda de forma automatizada. Um pacote de integração do Visual Studio também está disponível para ele para que os projetos de ajuda possam ser criados e gerenciados inteiramente de dentro do Visual Studio.
  • Doxygen: O Doxygen gera um navegador de documentação online (em HTML) ou um manual de referência offline (em LaTeX) de um conjunto de arquivos de origem documentados. Também há suporte para gerar saída em páginas manuais RTF (MS Word), PostScript, PDF hiperlink, HTML compactado, DocBook e Unix. Você pode configurar o Doxygen para extrair a estrutura de código de arquivos de origem não documentados.

Observação

Os comentários da documentação XML não são metadados; eles não são incluídos no assembly compilado e, portanto, não são acessíveis por meio da reflexão.

Cadeias de caracteres de ID

Cada tipo ou membro é armazenado em um elemento no arquivo XML de saída. Cada um desses elementos tem uma cadeia de caracteres de ID exclusiva que identifica o tipo ou membro. A cadeia de caracteres de ID deve considerar operadores, parâmetros, valores retornados, parâmetros refinde tipo genérico e out parâmetros. Para codificar todos esses elementos potenciais, o compilador segue regras claramente definidas para gerar as cadeias de caracteres de ID. Os programas que processam o arquivo XML usam a cadeia de caracteres de ID para identificar os metadados do .NET correspondentes ou o item de reflexão ao qual a documentação se aplica.

O compilador observa as seguintes regras quando gera as cadeias de caracteres de ID:

  • Nenhum espaço em branco está na cadeia de caracteres.

  • A primeira parte da cadeia de caracteres identifica o tipo de membro usando um único caractere seguido por dois-pontos. Os seguintes tipos de membro são usados:

    Personagem Tipo de membro Anotações
    N espaço para nome Você não pode adicionar comentários de documentação a um namespace, mas pode fazer cref referências a eles, onde houver suporte.
    T tipo Um tipo é uma classe, interface, struct, enum ou delegado.
    F campo
    P propriedade Inclui indexadores ou outras propriedades indexadas.
    M método Inclui métodos especiais, como construtores e operadores.
    E evento
    ! cadeia de caracteres de erro O restante da cadeia de caracteres fornece informações sobre o erro. O compilador C# gera informações de erro para links que não podem ser resolvidos.
  • A segunda parte da cadeia de caracteres é o nome totalmente qualificado do item, começando na raiz do namespace. O nome do item, seus tipos de delimitamento e namespace são separados por períodos. Se o nome do item em si tiver períodos, eles serão substituídos pelo sinal de hash ('#'). A gramática pressupõe que nenhum item tenha um sinal de hash diretamente em seu nome. Por exemplo, o nome totalmente qualificado do construtor String é "System.String.#ctor".

  • Para propriedades e métodos, a lista de parâmetros entre parênteses segue. Se não houver parâmetros, nenhum parêntese estará presente. Os parâmetros são separados por vírgulas. A codificação de cada parâmetro segue diretamente como ele é codificado em uma assinatura do .NET (consulte Microsoft.VisualStudio.CorDebugInterop.CorElementType as definições de todos os elementos caps na lista a seguir):

    • Tipos base. Tipos regulares (ELEMENT_TYPE_CLASS ou ELEMENT_TYPE_VALUETYPE) são representados como o nome totalmente qualificado do tipo.
    • Tipos intrínsecos (por exemplo, ELEMENT_TYPE_I4, ELEMENT_TYPE_OBJECT, ELEMENT_TYPE_STRING, e ELEMENT_TYPE_VOIDELEMENT_TYPE_TYPEDBYREF) são representados como o nome totalmente qualificado do tipo completo correspondente. Por exemplo, System.Int32 ou System.TypedReference.
    • ELEMENT_TYPE_PTR é representado como um '*' seguindo o tipo modificado.
    • ELEMENT_TYPE_BYREF é representado como um '@' seguindo o tipo modificado.
    • ELEMENT_TYPE_CMOD_OPT é representado como um '!' e o nome totalmente qualificado da classe modificadora, seguindo o tipo modificado.
    • ELEMENT_TYPE_SZARRAY é representado como "[]" seguindo o tipo de elemento da matriz.
    • ELEMENT_TYPE_ARRAY é representado como [limite inferior:size,limite inferior:size] em que o número de vírgulas é a classificação - 1, e os limites inferiores e o tamanho de cada dimensão, se conhecido, são representados em decimal. O limite e o tamanho inferiores serão omitidos se não forem especificados. Se o limite inferior e o tamanho de uma determinada dimensão forem omitidos, o ':' também será omitido. Por exemplo, uma matriz bidimensional com 1 como os limites inferiores e tamanhos não especificados é [1:,1:].
  • Somente para operadores de conversão (op_Implicit e op_Explicit), o valor retornado do método é codificado como um ~ seguido pelo tipo de retorno. Por exemplo: <member name="M:System.Decimal.op_Explicit(System.Decimal arg)~System.Int32"> é a marca para o operador public static explicit operator int (decimal value); cast declarado na System.Decimal classe.

  • Para tipos genéricos, o nome do tipo é seguido por um backtick e, em seguida, um número que indica o número de parâmetros de tipo genérico. Por exemplo: <member name="T:SampleClass`2"> é a marca para um tipo definido como public class SampleClass<T, U>. Para métodos que tomam tipos genéricos como parâmetros, os parâmetros de tipo genérico são especificados como números precedidos por backticks (por exemplo, '0,'1). Cada número representa uma notação de matriz baseada em zero para os parâmetros genéricos do tipo.

    • ELEMENT_TYPE_PINNED é representado como um '^' após o tipo modificado. O compilador C# nunca gera essa codificação.
    • ELEMENT_TYPE_CMOD_REQ é representado como um '|' e o nome totalmente qualificado da classe modificadora, seguindo o tipo modificado. O compilador C# nunca gera essa codificação.
    • ELEMENT_TYPE_GENERICARRAY é representado como "[?]" seguindo o tipo de elemento da matriz. O compilador C# nunca gera essa codificação.
    • ELEMENT_TYPE_FNPTR é representado como "=FUNC:type(signature)", onde type está o tipo de retorno e a assinatura são os argumentos do método. Se não houver argumentos, os parênteses serão omitidos. O compilador C# nunca gera essa codificação.
    • Os seguintes componentes de assinatura não são representados porque não são usados para diferenciar métodos sobrecarregados:
      • convenção de chamada
      • tipo de retorno
      • ELEMENT_TYPE_SENTINEL

Os exemplos a seguir mostram como as cadeias de caracteres de ID de uma classe e seus membros são geradas:

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;
}

Especificação da linguagem C#

Para obter mais informações, consulte o anexo da Especificação da Linguagem C# nos comentários da documentação.