Compartir a través de


Comentarios de la documentación del anexo D

Este anexo es informativo.

D.1 General

C# proporciona un mecanismo para que los programadores documenten su código mediante una sintaxis de comentario que contiene texto XML. En los archivos de código fuente, los comentarios que tienen un formato determinado se pueden usar para dirigir una herramienta para generar XML a partir de esos comentarios y los elementos de código fuente, que preceden. Los comentarios que usan esta sintaxis se denominan comentarios de documentación. Deben preceder inmediatamente a un tipo definido por el usuario (como una clase, un delegado o una interfaz) o un miembro (como un campo, evento, propiedad o método). La herramienta de generación XML se denomina generador de documentación. (Este generador podría ser, pero no es necesario, el propio compilador de C#). La salida generada por el generador de documentación se denomina archivo de documentación. Un archivo de documentación se usa como entrada para un visor de documentación; una herramienta destinada a generar algún tipo de visualización visual de información de tipo y su documentación asociada.

No es necesario un compilador de C# conforme para comprobar la sintaxis de los comentarios de documentación; estos comentarios son simplemente comentarios ordinarios. Sin embargo, se permite que un compilador conforme realice esta comprobación.

Esta especificación sugiere un conjunto de etiquetas estándar que se usarán en los comentarios de documentación, pero no se requiere el uso de estas etiquetas y se pueden usar otras etiquetas si se desea, siempre y cuando se sigan las reglas de XML bien formado. En el caso de las implementaciones de C# destinadas a la CLI, también proporciona información sobre el generador de documentación y el formato del archivo de documentación. No se proporciona información sobre el visor de documentación.

Introducción a D.2

Los comentarios que tienen un formulario determinado se pueden usar para dirigir una herramienta para generar XML a partir de esos comentarios y los elementos de código fuente que preceden. Estos comentarios son Single_Line_Comment s (§6.3.3) que comienzan con tres barras diagonales (///) o Delimited_Comments (§6.3.3) que comienzan con una barra diagonal y dos asteriscos (/**). Deben preceder inmediatamente a un tipo definido por el usuario o a un miembro que anotan. Las secciones de atributo (§22.3) se consideran parte de las declaraciones, por lo que los comentarios de documentación deben preceder a los atributos aplicados a un tipo o miembro.

Con fines expositores, el formato de los comentarios del documento se muestra a continuación como dos reglas gramaticales: Single_Line_Doc_Comment y Delimited_Doc_Comment. Sin embargo, estas reglas no forman parte de la gramática de C#, sino que representan formatos concretos de Single_Line_Comment y reglas de lexer Delimited_Comment, respectivamente.

Sintaxis:

Single_Line_Doc_Comment
    : '///' Input_Character*
    ;
   
Delimited_Doc_Comment
    : '/**' Delimited_Comment_Section* ASTERISK+ '/'
    ;

En un Single_Line_Doc_Comment, si hay un carácter de espacio en blanco después de los /// caracteres de cada uno de los Single_Line_Doc_Comments adyacentes al Single_Line_Doc_Comment actual, ese carácter de espacio en blanco no se incluye en la salida XML.

En un Delimited_Doc_Comment, si el primer carácter no en blanco de la segunda línea es un ASTERISK y el mismo patrón de caracteres opcionales de espacio en blanco y se repite un carácter ASTERISK al principio de cada una de las líneas de la Delimited_Doc_Comment, los caracteres del patrón repetido no se incluyen en la salida XML. El patrón puede incluir caracteres de espacio en blanco después, así como antes, el carácter ASTERISK .

Ejemplo:

/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
public class Point
{
    /// <summary>
    /// Method <c>Draw</c> renders the point.
    /// </summary>
    void Draw() {...}
}

El texto de los comentarios de documentación debe estar bien formado según las reglas de XML (http://www.w3.org/TR/REC-xml). Si el XML tiene un formato incorrecto, se genera una advertencia y el archivo de documentación contendrá un comentario que indica que se encontró un error.

Aunque los desarrolladores pueden crear su propio conjunto de etiquetas, se define un conjunto recomendado en §D.3. Algunas de las etiquetas recomendadas tienen significados especiales:

  • La etiqueta <param> se usa para describir parámetros. Si se usa dicha etiqueta, el generador de documentación debe comprobar que existe el parámetro especificado y que todos los parámetros se describen en los comentarios de la documentación. Si se produce un error en dicha comprobación, el generador de documentación emite una advertencia.

  • El atributo cref se puede asociar a cualquier etiqueta para proporcionar una referencia a un elemento de código. El generador de documentación debe comprobar que este elemento de código existe. Si se produce un error en la comprobación, el generador de documentación emite una advertencia. Al buscar un nombre descrito en un cref atributo, el generador de documentación debe respetar la visibilidad del espacio de nombres según las instrucciones using que aparecen en el código fuente. En el caso de los elementos de código genéricos, no se puede usar la sintaxis genérica normal (por ejemplo, "List<T>") porque genera XML no válido. Las llaves se pueden usar en lugar de corchetes (por ejemplo; "List{T}"), o se puede usar la sintaxis de escape XML (por ejemplo, "List&lt;T&gt;").

  • La <summary> etiqueta está pensada para ser utilizada por un visor de documentación para mostrar información adicional sobre un tipo o miembro.

  • La <include> etiqueta incluye información de un archivo XML externo.

Tenga en cuenta cuidadosamente que el archivo de documentación no proporciona información completa sobre el tipo y los miembros (por ejemplo, no contiene ninguna información de tipo). Para obtener esta información sobre un tipo o miembro, el archivo de documentación debe usarse junto con la reflexión sobre el tipo o miembro.

D.3.1 General

El generador de documentación debe aceptar y procesar cualquier etiqueta válida según las reglas de XML. Las etiquetas siguientes proporcionan funciones de uso general en la documentación de usuario. (Por supuesto, otras etiquetas son posibles).

Tag Referencia Propósito
<c> §D.3.2 Establecer texto en una fuente similar a código
<code> §D.3.3 Establecer una o varias líneas de código fuente o salida del programa
<example> §D.3.4 Indicar un ejemplo
<exception> §D.3.5 Identifica las excepciones que un método puede producir
<include> §D.3.6 Incluye XML de un archivo externo
<list> §D.3.7 Creación de una lista o tabla
<para> §D.3.8 Permitir que la estructura se agregue al texto
<param> §D.3.9 Describir un parámetro para un método o constructor
<paramref> §D.3.10 Identificar que una palabra es un nombre de parámetro
<permission> §D.3.11 Documentar la accesibilidad de seguridad de un miembro
<remarks> §D.3.12 Describir información adicional sobre un tipo
<returns> §D.3.13 Describir el valor devuelto de un método
<see> §D.3.14 Especificar un vínculo
<seealso> §D.3.15 Generación de una entrada See Also
<summary> §D.3.16 Describir un tipo o un miembro de un tipo
<typeparam> §D.3.17 Describir un parámetro de tipo para un tipo o método genéricos
<typeparamref> §D.3.18 Identificar que una palabra es un nombre de parámetro de tipo
<value> §D.3.19 Describir una propiedad

D.3.2 <c>

Esta etiqueta proporciona un mecanismo para indicar que un fragmento de texto dentro de una descripción debe establecerse en una fuente especial, como la que se usa para un bloque de código. Para las líneas de código real, use <code> (§D.3.3).

Sintaxis:

<c>text</c>

Ejemplo:

/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
public class Point
{
}

Código D.3.3 <>

Esta etiqueta se usa para establecer una o varias líneas de código fuente o salida de programa en alguna fuente especial. Para fragmentos de código pequeños en narración, use <c> (§D.3.2).

Sintaxis:

<code>código fuente o salida del programa</code>

Ejemplo:

public class Point
{
    /// <summary>
    /// This method changes the point's location by the given x- and y-offsets.
    /// <example>
    /// For example:
    /// <code>
    /// Point p = new Point(3,5);
    /// p.Translate(-1,3);
    /// </code>
    /// results in <c>p</c>'s having the value (2,8).
    /// </example>
    /// </summary>
    public void Translate(int dx, int dy)
    {
        ...
    }
}

Ejemplo de D.3.4 <>

Esta etiqueta permite el código de ejemplo dentro de un comentario para especificar cómo se puede usar un método u otro miembro de biblioteca. Normalmente, esto también implicaría el uso de la etiqueta <code> (§D.3.3) también.

Sintaxis:

<example>descripción</example>

Ejemplo:

Consulte <code> (§D.3.3) para obtener un ejemplo.

Excepción D.3.5 <>

Esta etiqueta proporciona una manera de documentar las excepciones que puede producir un método.

Sintaxis:

<exception cref="descripción del miembro"></exception>

where

  • cref="member" es el nombre de un miembro. El generador de documentación comprueba que el miembro especificado existe y traduce el miembro al nombre del elemento canónico en el archivo de documentación.
  • description es una descripción de las circunstancias en las que se produce la excepción.

Ejemplo:

class PrimaryFileFormatCorruptException : System.Exception { ... }
class PrimaryFileLockedOpenException : System.Exception { ... }

public class DataBaseOperations
{
    /// <exception cref="PrimaryFileFormatCorruptException">
    /// Thrown when the primary file is corrupted.
    /// </exception>
    /// <exception cref="PrimaryFileLockedOpenException">
    /// Thrown when the primary file is already open.
    /// </exception>
    public static void ReadRecord(int flag)
    {
        if (flag == 1)
        {
            throw new PrimaryFileFormatCorruptException();
        }
        else if (flag == 2)
        {
            throw new PrimaryFileLockedOpenException();
        }
        ...
    }
}

D.3.6 <include>

Esta etiqueta permite incluir información de un documento XML externo al archivo de código fuente. El archivo externo debe ser un documento XML bien formado y se aplica una expresión XPath a ese documento para especificar qué XML de ese documento se va a incluir. A <include> continuación, la etiqueta se reemplaza por el XML seleccionado del documento externo.

Sintaxis:

<include file="nombre de archivo" path="xpath" />

where

  • file="filename" es el nombre de archivo de un archivo XML externo. El nombre de archivo se interpreta en relación con el archivo que contiene la etiqueta include.
  • path="xpath" es una expresión XPath que selecciona parte del XML en el archivo XML externo.

Ejemplo:

Si el código fuente contenía una declaración como:

/// <include file="docs.xml" path='extradoc/class[@name="IntList"]/*' />
public class IntList { ... }

y el archivo externo "docs.xml" tenían el siguiente contenido:

<?xml version="1.0"?>
<extradoc>
    <class name="IntList">
        <summary>
            Contains a list of integers.
        </summary>
    </class>
    <class name="StringList">
        <summary>
            Contains a list of strings.
        </summary>
    </class>
</extradoc>

a continuación, se genera la misma documentación que si el código fuente contenía:

/// <summary>
/// Contains a list of integers.
/// </summary>
public class IntList { ... }

Lista D.3.7 <>

Esta etiqueta se usa para crear una lista o una tabla de elementos. Puede contener un <listheader> bloque para definir la fila de encabezado de una tabla o lista de definiciones. (Al definir una tabla, solo se debe proporcionar una entrada para el término en el encabezado).

Cada elemento de la lista se especifica con un bloque <item>. Al crear una lista de definiciones, debe especificarse tanto el término como la descripción . Sin embargo, para una tabla, una lista con viñetas o una lista numerada, solo es necesario especificar la descripción .

Sintaxis:

<list type="bullet" | "number" | "table">
    <listheader>
        <term>term</term>
        <description>description</description>
    </listheader>
    <item>
        <term>term</term>
        <description>description</description>
    </item>
    ...
    <item>
        <term>term</term>
        <description>description</description>
    </item>
</list>

where

  • term es el término que se va a definir, cuya definición está en descripción.
  • description es un elemento de una lista numerada o viñeta o la definición de un término.

Ejemplo:

public class MyClass
{
    /// <summary>Here is an example of a bulleted list:
    /// <list type="bullet">
    /// <item>
    /// <description>Item 1.</description>
    /// </item>
    /// <item>
    /// <description>Item 2.</description>
    /// </item>
    /// </list>
    /// </summary>
    public static void Main()
    {
        ...
    }
}

D.3.8 <para>

Esta etiqueta se usa dentro de otras etiquetas, como <summary> (§D.3.16) o <returns> (§D.3.13) y permite agregar la estructura al texto.

Sintaxis:

<para>content</para>

where

  • content es el texto del párrafo.

Ejemplo:

public class Point
{
    /// <summary>This is the entry point of the Point class testing program.
    /// <para>
    /// This program tests each method and operator, and
    /// is intended to be run after any non-trivial maintenance has
    /// been performed on the Point class.
    /// </para>
    /// </summary>
    public static void Main() 
    {
        ...
    }
}

D.3.9 <param>

Esta etiqueta se usa para describir un parámetro para un método, constructor o indexador.

Sintaxis:

<param name="nombre">descripción</param>

where

  • name es el nombre del parámetro .
  • description es una descripción del parámetro .

Ejemplo:

public class Point
{
    /// <summary>
    /// This method changes the point's location to
    /// the given coordinates.
    /// </summary>
    /// <param name="xPosition">the new x-coordinate.</param>
    /// <param name="yPosition">the new y-coordinate.</param>
    public void Move(int xPosition, int yPosition)
    {
        ...
    }
}

D.3.10 <paramref>

Esta etiqueta se usa para indicar que una palabra es un parámetro. El archivo de documentación se puede procesar para dar formato a este parámetro de alguna manera distinta.

Sintaxis:

<paramref name="name"/>

where

  • name es el nombre del parámetro .

Ejemplo:

public class Point
{
    /// <summary>This constructor initializes the new Point to
    /// (<paramref name="xPosition"/>,<paramref name="yPosition"/>).
    /// </summary>
    /// <param name="xPosition">the new Point's x-coordinate.</param>
    /// <param name="yPosition">the new Point's y-coordinate.</param>
    public Point(int xPosition, int yPosition)
    {
        ...
    }
}

Permiso D.3.11 <>

Esta etiqueta permite documentar la accesibilidad de seguridad de un miembro.

Sintaxis:

<permission cref="descripción del miembro"></permission>

where

  • member es el nombre de un miembro. El generador de documentación comprueba que el elemento de código dado existe y traduce el miembro al nombre del elemento canónico en el archivo de documentación.
  • description es una descripción del acceso al miembro.

Ejemplo:

public class MyClass
{
    /// <permission cref="System.Security.PermissionSet">
    /// Everyone can access this method.
    /// </permission>
    public static void Test()
    {
        ...
    }
}

Comentarios D.3.12 <>

Esta etiqueta se usa para especificar información adicional sobre un tipo. Use <summary> (§D.3.16) para describir el propio tipo y los miembros de un tipo.

Sintaxis:

<remarks>descripción</remarks>

where

  • description es el texto del comentario.

Ejemplo:

/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
/// <remarks>
/// Uses polar coordinates
/// </remarks>
public class Point
{
    ...
}

Devuelve D.3.13 <>

Esta etiqueta se usa para describir el valor devuelto de un método.

Sintaxis:

<returns>descripción</returns>

where

  • description es una descripción del valor devuelto.

Ejemplo:

public class Point
{
    /// <summary>
    /// Report a point's location as a string.
    /// </summary>
    /// <returns>
    /// A string representing a point's location, in the form (x,y),
    /// without any leading, trailing, or embedded whitespace.
    /// </returns>
    public override string ToString() => $"({X},{Y})";
    public int X { get; set; }
    public int Y { get; set; }
}

D.3.14 <ver>

Esta etiqueta permite especificar un vínculo dentro del texto. Use <seealso> (§D.3.15) para indicar el texto que se va a mostrar en una subclausa See Also .

Sintaxis:

<see cref="palabra clave url" langword="de miembro" href="" />

where

  • member es el nombre de un miembro. El generador de documentación comprueba que el elemento de código especificado existe y cambia el miembro al nombre del elemento en el archivo de documentación generado.
  • url es una referencia a un origen externo.
  • langword es una palabra que se va a resaltar de alguna manera.

Ejemplo:

public class Point
{
    /// <summary>
    /// This method changes the point's location to
    /// the given coordinates. <see cref="Translate"/>
    /// </summary>
    public void Move(int xPosition, int yPosition)
    {
        ...
    }
    /// <summary>This method changes the point's location by
    /// the given x- and y-offsets. <see cref="Move"/>
    /// </summary>
    public void Translate(int dx, int dy)
    {
        ...
    }
}

D.3.15 <seealso>

Esta etiqueta permite generar una entrada para la subclausa Ver también . Use <see> (§D.3.14) para especificar un vínculo desde el texto.

Sintaxis:

<seealso cref="dirección URL de miembro" href="" />

where

  • member es el nombre de un miembro. El generador de documentación comprueba que el elemento de código especificado existe y cambia el miembro al nombre del elemento en el archivo de documentación generado.
  • url es una referencia a un origen externo.

Ejemplo:

public class Point
{
    /// <summary>
    /// This method determines whether two Points have the same location.
    /// </summary>
    /// <seealso cref="operator=="/>
    /// <seealso cref="operator!="/>
    public override bool Equals(object o)
    {
        ...
    }
}

Resumen de D.3.16 <>

Esta etiqueta se puede usar para describir un tipo o un miembro de un tipo. Use <remarks> (§D.3.12) para especificar información adicional sobre el tipo o miembro.

Sintaxis:

<summary>descripción</summary>

where

  • description es un resumen del tipo o miembro.

Ejemplo:

public class Point
{

    /// <summary>
    /// This constructor initializes the new Point to
    /// (<paramref name="xPosition"/>,<paramref name="yPosition"/>).
    /// </summary>
    public Point(int xPosition, int yPosition) 
    {
        ...
    }

    /// <summary>This constructor initializes the new Point to (0,0).</summary>
    public Point() : this(0, 0)
    {
    }
}

D.3.17 <typeparam>

Esta etiqueta se usa para describir un parámetro de tipo para un tipo o método genéricos.

Sintaxis:

<typeparam name="nombre">descripción</typeparam>

where

  • name es el nombre del parámetro de tipo.
  • description es una descripción del parámetro de tipo.

Ejemplo:

/// <summary>A generic list class.</summary>
/// <typeparam name="T">The type stored by the list.</typeparam>
public class MyList<T>
{
   ...
}

D.3.18 <typeparamref>

Esta etiqueta se usa para indicar que una palabra es un parámetro de tipo. El archivo de documentación se puede procesar para dar formato a este parámetro de tipo de alguna manera distinta.

Sintaxis:

<typeparamref name="name"/>

where

  • name es el nombre del parámetro de tipo.

Ejemplo:

public class MyClass
{
    /// <summary>
    /// This method fetches data and returns a list of
    /// <typeparamref name="T"/>.
    /// </summary>
    /// <param name="query">query to execute</param>
    public List<T> FetchData<T>(string query)
    {
        ...
    }
}

Valor D.3.19 <>

Esta etiqueta permite describir una propiedad.

Sintaxis:

<value>descripción de la propiedad</value>

where

  • la descripción de la propiedad es una descripción de la propiedad.

Ejemplo:

public class Point
{
    /// <value>Property <c>X</c> represents the point's x-coordinate.</value>
    public int X { get; set; }
}

D.4 Procesamiento del archivo de documentación

D.4.1 General

La siguiente información está pensada para implementaciones de C# destinadas a la CLI.

El generador de documentación genera una cadena de identificador para cada elemento del código fuente etiquetado con un comentario de documentación. Esta cadena de identificador identifica de forma única un elemento de origen. Un visor de documentación puede usar una cadena de identificador para identificar el elemento correspondiente al que se aplica la documentación.

El archivo de documentación no es una representación jerárquica del código fuente; en su lugar, es una lista plana con una cadena de identificador generada para cada elemento.

Formato de cadena de identificador D.4.2

El generador de documentación observa las siguientes reglas cuando genera las cadenas de identificador:

  • No se coloca espacio en blanco en la cadena.

  • La primera parte de la cadena identifica el tipo de miembro que se documenta, a través de un solo carácter seguido de dos puntos. Se definen los siguientes tipos de miembros:

    Carácter Descripción
    E Evento
    F Campo
    M Método (incluidos constructores, finalizadores y operadores)
    N Espacio de nombres
    P Propiedad (incluidos los indexadores)
    T Tipo (por ejemplo, clase, delegado, enumeración, interfaz y estructura)
    ! Cadena de error; el resto de la cadena proporciona información sobre el error. Por ejemplo, el generador de documentación genera información de error para vínculos que no se pueden resolver.
  • La segunda parte de la cadena es el nombre completo del elemento, empezando por la raíz del espacio de nombres. El nombre del elemento, sus tipos envolventes y el espacio de nombres están separados por puntos. Si el nombre del elemento tiene puntos, se reemplazan por caracteres # (U+0023). (Se supone que ningún elemento tiene este carácter en su nombre). Los argumentos de tipo en el nombre completo, para cuando un miembro implementa explícitamente un miembro de una interfaz genérica, se codifican reemplazando los caracteres "<" y ">" que los rodean por los caracteres "{" y "}".

  • Para los métodos y propiedades con argumentos, la lista de argumentos sigue, entre paréntesis. Para aquellos sin argumentos, se omiten los paréntesis. Los argumentos están separados por comas. La codificación de cada argumento es la misma que una firma de la CLI, como se indica a continuación:

    • Los argumentos se representan mediante su nombre de documentación, que se basa en su nombre completo, modificado de la siguiente manera:
      • Los argumentos que representan tipos genéricos tienen un carácter "'" anexado seguido del número de parámetros de tipo.
      • Los argumentos que tienen el inmodificador , out o ref tienen un @ siguiente nombre de tipo. Los argumentos pasados por valor o a través params de no tienen notación especial.
      • Los argumentos que son matrices se representan como [ tamaño , de entrada : inferior... ,lowerbound : tamaño ] donde el número de comas es el rango menor, y los límites y el tamaño inferiores de cada dimensión, si se conocen, se representan en decimal. Si no se especifica un límite inferior o un tamaño, se omite. Si se omite el límite inferior y el tamaño de una dimensión determinada, también se omite ":". Las matrices escalonadas se representan mediante una "[]" por nivel. Las matrices unidimensionales omiten el límite inferior cuando el límite inferior es 0 (valor predeterminado) (§17.1).
      • Los argumentos que tienen tipos de puntero distintos void de se representan mediante un * siguiente nombre de tipo. Un void puntero se representa mediante un nombre de tipo de System.Void.
      • Los argumentos que hacen referencia a parámetros de tipo genérico definidos en los tipos se codifican mediante el carácter "`" seguido del índice de base cero del parámetro de tipo.
      • Los argumentos que usan parámetros de tipo genérico definidos en métodos usan un doble retroceso "``" en lugar de "`" que se usa para los tipos.
      • Los argumentos que hacen referencia a tipos genéricos construidos se codifican mediante el tipo genérico, seguido de "{", seguido de una lista separada por comas de argumentos de tipo, seguido de "}".

Ejemplos de cadenas de identificador D.4.3

En los ejemplos siguientes se muestra un fragmento de código de C#, junto con la cadena de identificador generada a partir de cada elemento de origen capaz de tener un comentario de documentación:

Los tipos se representan con su nombre completo, aumentado con información genérica:

enum Color { Red, Blue, Green }

namespace Acme
{
    interface IProcess { ... }

    struct ValueType { ... }

    class Widget : IProcess
    {
        public class NestedClass { ... }
        public interface IMenuItem { ... }
        public delegate void Del(int i);
        public enum Direction { North, South, East, West }
    }

    class MyList<T>
    {
        class Helper<U,V> { ... }
    }
}

Identificadores:

"T:Color"
"T:Acme.IProcess"
"T:Acme.ValueType"
"T:Acme.Widget"
"T:Acme.Widget.NestedClass"
"T:Acme.Widget.IMenuItem"
"T:Acme.Widget.Del"
"T:Acme.Widget.Direction"
"T:Acme.MyList`1"
"T:Acme.MyList`1.Helper`2"

Los campos se representan mediante su nombre completo.

namespace Acme
{
    struct ValueType
    {
        private int total;
    }

    class Widget : IProcess
    {
        public class NestedClass
        {
            private int value;
        }

        private string message;
        private static Color defaultColor;
        private const double PI = 3.14159;
        protected readonly double monthlyAverage;
        private long[] array1;
        private Widget[,] array2;
        private unsafe int *pCount;
        private unsafe float **ppValues;
    }
}

Identificadores:

"F:Acme.ValueType.total"
"F:Acme.Widget.NestedClass.value"
"F:Acme.Widget.message"
"F:Acme.Widget.defaultColor"
"F:Acme.Widget.PI"
"F:Acme.Widget.monthlyAverage"
"F:Acme.Widget.array1"
"F:Acme.Widget.array2"
"F:Acme.Widget.pCount"
"F:Acme.Widget.ppValues"

Constructores

namespace Acme
{
    class Widget : IProcess
    {
        static Widget() { ... }
        public Widget() { ... }
        public Widget(string s) { ... }
    }
}

Identificadores:

"M:Acme.Widget.#cctor"
"M:Acme.Widget.#ctor"
"M:Acme.Widget.#ctor(System.String)"

Finalizadores

namespace Acme
{
    class Widget : IProcess
    {
        ~Widget() { ... }
    }
}

Identificadores:

"M:Acme.Widget.Finalize"

Métodos

namespace Acme
{
    struct ValueType
    {
        public void M(int i) { ... }
    }

    class Widget : IProcess
    {
        public class NestedClass
        {
            public void M(int i) { ... }
        }

        public static void M0() { ... }
        public void M1(char c, out float f, ref ValueType v, in int i) { ... }
        public void M2(short[] x1, int[,] x2, long[][] x3) { ... }
        public void M3(long[][] x3, Widget[][,,] x4) { ... }
        public unsafe void M4(char *pc, Color **pf) { ... }
        public unsafe void M5(void *pv, double *[][,] pd) { ... }
        public void M6(int i, params object[] args) { ... }
    }

    class MyList<T>
    {
        public void Test(T t) { ... }
    }

    class UseList
    {
        public void Process(MyList<int> list) { ... }
        public MyList<T> GetValues<T>(T value) { ... } 
    }
}

Identificadores:

"M:Acme.ValueType.M(System.Int32)"
"M:Acme.Widget.NestedClass.M(System.Int32)"
"M:Acme.Widget.M0"
"M:Acme.Widget.M1(System.Char,System.Single@,Acme.ValueType@,System.Int32@)"
"M:Acme.Widget.M2(System.Int16[],System.Int32[0:,0:],System.Int64[][])"
"M:Acme.Widget.M3(System.Int64[][],Acme.Widget[0:,0:,0:][])"
"M:Acme.Widget.M4(System.Char*,Color**)"
"M:Acme.Widget.M5(System.Void*,System.Double*[0:,0:][])"
"M:Acme.Widget.M6(System.Int32,System.Object[])"
"M:Acme.MyList`1.Test(`0)"
"M:Acme.UseList.Process(Acme.MyList{System.Int32})"
"M:Acme.UseList.GetValues``1(``0)"

Propiedades e indizadores

namespace Acme
{
    class Widget : IProcess
    {
        public int Width { get { ... } set { ... } }
        public int this[int i] { get { ... } set { ... } }
        public int this[string s, int i] { get { ... } set { ... } }
    }
}

Identificadores:

"P:Acme.Widget.Width"
"P:Acme.Widget.Item(System.Int32)"
"P:Acme.Widget.Item(System.String,System.Int32)"

Eventos

namespace Acme
{
    class Widget : IProcess
    {
        public event Del AnEvent;
    }
}

Identificadores:

"E:Acme.Widget.AnEvent"

Operadores unarios

namespace Acme
{
    class Widget : IProcess
    {
        public static Widget operator+(Widget x) { ... }
    }
}

Identificadores:

"M:Acme.Widget.op_UnaryPlus(Acme.Widget)"

El conjunto completo de nombres de función de operador unarios usados es el siguiente: op_UnaryPlus, op_UnaryNegation, op_LogicalNot, op_OnesComplementop_Increment, , op_Decrementop_Truey op_False.

Operadores binarios

namespace Acme
{
    class Widget : IProcess
    {
        public static Widget operator+(Widget x1, Widget x2) { ... }
    }
}

Identificadores:

"M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget)"

El conjunto completo de nombres de función de operador binario usados es el siguiente: op_Addition, op_Subtraction, op_Modulusop_Divisionop_ExclusiveOrop_LeftShiftop_BitwiseOrop_RightShiftop_Equalityop_BitwiseAndop_Multiplyop_LessThanop_LessThanOrEqualop_Inequalityop_GreaterThany .op_GreaterThanOrEqual

Los operadores de conversión tienen un "~" final seguido del tipo de valor devuelto. Cuando el origen o el destino de un operador de conversión es un tipo genérico, los caracteres "<" y "">" se reemplazan por los caracteres "{" y "}", respectivamente.

namespace Acme
{
    class Widget : IProcess
    {
        public static explicit operator int(Widget x) { ... }
        public static implicit operator long(Widget x) { ... }
    }
}

Identificadores:

"M:Acme.Widget.op_Explicit(Acme.Widget)~System.Int32"
"M:Acme.Widget.op_Implicit(Acme.Widget)~System.Int64"

D.5 Un ejemplo

Código fuente de C# D.5.1

En el ejemplo siguiente se muestra el código fuente de una clase Point:

namespace Graphics
{
    /// <summary>
    /// Class <c>Point</c> models a point in a two-dimensional plane.
    /// </summary>
    public class Point
    {
        /// <value>
        /// Property <c>X</c> represents the point's x-coordinate.
        /// </value>
        public int X { get; set; }
        
        /// <value>
        /// Property <c>Y</c> represents the point's y-coordinate.
        /// </value>
        public int Y { get; set; }
        
        /// <summary>
        /// This constructor initializes the new Point to (0,0).
        /// </summary>
        public Point() : this(0, 0) {}
        
        /// <summary>
        /// This constructor initializes the new Point to
        /// (<paramref name="xPosition"/>,<paramref name="yPosition"/>).
        /// </summary>
        /// <param name="xPosition">The new Point's x-coordinate.</param>
        /// <param name="yPosition">The new Point's y-coordinate.</param>
        public Point(int xPosition, int yPosition) 
        {
            X = xPosition;
            Y = yPosition;
        }
        
        /// <summary>
        /// This method changes the point's location to
        /// the given coordinates. <see cref="Translate"/>
        /// </summary>
        /// <param name="xPosition">The new x-coordinate.</param>
        /// <param name="yPosition">The new y-coordinate.</param>
        public void Move(int xPosition, int yPosition) 
        {
            X = xPosition;
            Y = yPosition;
        }
        
        /// <summary>
        /// This method changes the point's location by
        /// the given x- and y-offsets.
        /// <example>For example:
        /// <code>
        /// Point p = new Point(3, 5);
        /// p.Translate(-1, 3);
        /// </code>
        /// results in <c>p</c>'s having the value (2, 8).
        /// <see cref="Move"/>
        /// </example>
        /// </summary>
        /// <param name="dx">The relative x-offset.</param>
        /// <param name="dy">The relative y-offset.</param>
        public void Translate(int dx, int dy)
        {
            X += dx;
            Y += dy;
        }
        
        /// <summary>
        /// This method determines whether two Points have the same location.
        /// </summary>
        /// <param name="o">
        /// The object to be compared to the current object.
        /// </param>
        /// <returns>
        /// True if the Points have the same location and they have
        /// the exact same type; otherwise, false.
        /// </returns>
        /// <seealso cref="operator=="/>
        /// <seealso cref="operator!="/>
        public override bool Equals(object o)
        {
            if (o == null)
            {
                return false;
            }
            if ((object)this == o) 
            {
                return true;
            }
            if (GetType() == o.GetType()) 
            {
                Point p = (Point)o;
                return (X == p.X) && (Y == p.Y);
            }
            return false;
        }

        /// <summary>
        /// This method returns a Point's hashcode.
        /// </summary>
        /// <returns>
        /// The int hashcode.
        /// </returns>
        public override int GetHashCode()
        {
            return X + (Y >> 4);    // a crude version
        }
        
        /// <summary>Report a point's location as a string.</summary>
        /// <returns>
        /// A string representing a point's location, in the form (x,y),
        /// without any leading, training, or embedded whitespace.
        /// </returns>
        public override string ToString() => $"({X},{Y})";
        
        /// <summary>
        /// This operator determines whether two Points have the same location.
        /// </summary>
        /// <param name="p1">The first Point to be compared.</param>
        /// <param name="p2">The second Point to be compared.</param>
        /// <returns>
        /// True if the Points have the same location and they have
        /// the exact same type; otherwise, false.
        /// </returns>
        /// <seealso cref="Equals"/>
        /// <seealso cref="operator!="/>
        public static bool operator==(Point p1, Point p2)
        {
            if ((object)p1 == null || (object)p2 == null)
            {
                return false;
            }
            if (p1.GetType() == p2.GetType())
            {
                return (p1.X == p2.X) && (p1.Y == p2.Y);
            }
            return false;
        }
        
        /// <summary>
        /// This operator determines whether two Points have the same location.
        /// </summary>
        /// <param name="p1">The first Point to be compared.</param>
        /// <param name="p2">The second Point to be compared.</param>
        /// <returns>
        /// True if the Points do not have the same location and the
        /// exact same type; otherwise, false.
        /// </returns>
        /// <seealso cref="Equals"/>
        /// <seealso cref="operator=="/>
        public static bool operator!=(Point p1, Point p2) => !(p1 == p2);
    }
}

D.5.2 XML resultante

Esta es la salida generada por un generador de documentación cuando se proporciona el código fuente para la clase Point, que se muestra anteriormente:

<?xml version="1.0"?>
<doc>
  <assembly>
    <name>Point</name>
  </assembly>
  <members>
    <member name="T:Graphics.Point">
    <summary>Class <c>Point</c> models a point in a two-dimensional
    plane.
    </summary>
    </member>
    <member name="M:Graphics.Point.#ctor">
      <summary>This constructor initializes the new Point to (0, 0).</summary>
    </member>
    <member name="M:Graphics.Point.#ctor(System.Int32,System.Int32)">
      <summary>
        This constructor initializes the new Point to
        (<paramref name="xPosition"/>,<paramref name="yPosition"/>).
      </summary>
      <param name="xPosition">The new Point's x-coordinate.</param>
      <param name="yPosition">The new Point's y-coordinate.</param>
    </member>
    <member name="M:Graphics.Point.Move(System.Int32,System.Int32)">
      <summary>
        This method changes the point's location to
        the given coordinates.
        <see cref="M:Graphics.Point.Translate(System.Int32,System.Int32)"/>
      </summary>
      <param name="xPosition">The new x-coordinate.</param>
      <param name="yPosition">The new y-coordinate.</param>
      </member>
    <member name="M:Graphics.Point.Translate(System.Int32,System.Int32)">
      <summary>
        This method changes the point's location by
        the given x- and y-offsets.
        <example>For example:
        <code>
        Point p = new Point(3,5);
        p.Translate(-1,3);
        </code>
        results in <c>p</c>'s having the value (2,8).
        </example>
        <see cref="M:Graphics.Point.Move(System.Int32,System.Int32)"/>
      </summary>
      <param name="dx">The relative x-offset.</param>
      <param name="dy">The relative y-offset.</param>
    </member>
    <member name="M:Graphics.Point.Equals(System.Object)">
      <summary>
        This method determines whether two Points have the same location.
      </summary>
      <param name="o">
        The object to be compared to the current object.
      </param>
      <returns>
        True if the Points have the same location and they have
        the exact same type; otherwise, false.
      </returns>
      <seealso 
        cref="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)" />
      <seealso 
        cref="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)"/>
    </member>
     <member name="M:Graphics.Point.ToString">
      <summary>
        Report a point's location as a string.
      </summary>
      <returns>
        A string representing a point's location, in the form (x,y),
        without any leading, training, or embedded whitespace.
      </returns>
     </member>
    <member name="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)">
      <summary>
        This operator determines whether two Points have the same location.
      </summary>
      <param name="p1">The first Point to be compared.</param>
      <param name="p2">The second Point to be compared.</param>
      <returns>
        True if the Points have the same location and they have
        the exact same type; otherwise, false.
      </returns>
      <seealso cref="M:Graphics.Point.Equals(System.Object)"/>
      <seealso
        cref="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)"/>
    </member>
    <member
        name="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)">
      <summary>
        This operator determines whether two Points have the same location.
      </summary>
      <param name="p1">The first Point to be compared.</param>
      <param name="p2">The second Point to be compared.</param>
      <returns>
        True if the Points do not have the same location and the
        exact same type; otherwise, false.
      </returns>
      <seealso cref="M:Graphics.Point.Equals(System.Object)"/>
      <seealso
        cref="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)"/>
      </member>
      <member name="M:Graphics.Point.Main">
        <summary>
          This is the entry point of the Point class testing program.
          <para>
            This program tests each method and operator, and
            is intended to be run after any non-trivial maintenance has
            been performed on the Point class.
          </para>
        </summary>
      </member>
      <member name="P:Graphics.Point.X">
        <value>
          Property <c>X</c> represents the point's x-coordinate.
        </value>
      </member>
      <member name="P:Graphics.Point.Y">
        <value>
          Property <c>Y</c> represents the point's y-coordinate.
        </value>
    </member>
  </members>
</doc>

Fin del texto informativo.