Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Este anexo es informativo.
D.1 Generalidades
C# proporciona un mecanismo para que los programadores documenten su código mediante una sintaxis de comentarios que contiene texto en XML. En los archivos de código fuente, los comentarios con una cierta forma pueden usarse para indicarle a una herramienta que genere XML a partir de esos comentarios y de los elementos del código fuente que los preceden. Los comentarios que usan esta sintaxis se llaman comentarios de documentación. Deben colocarse inmediatamente antes de un tipo definido por el usuario (como clase, delegado o interfaz) o de un miembro (como campo, evento, propiedad o método). La herramienta que genera el XML se llama generador de documentación. (Este generador podría ser, pero no necesariamente es, el propio compilador de C#). El resultado que produce el generador de documentación se llama archivo de documentación.. Un archivo de documentación se usa como entrada para un visor de documentación; una herramienta diseñada para generar una visualización de información tipográfica y su documentación asociada.
Un compilador de C# conforme no tiene la obligación de verificar la sintaxis de los comentarios de documentación; estos simplemente se consideran comentarios comunes. Sin embargo, un compilador conforme tiene permitido realizar dicha verificación.
Esta especificación sugiere un conjunto de etiquetas estándar para usar en los comentarios de documentación, pero no es obligatorio usarlas, y se pueden emplear otras etiquetas si así se desea, siempre que se respeten las reglas de un XML con el formato correcto. Para las implementaciones de C# dirigidas a la CLI, también se 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.
D.2 Introducción
Los comentarios con una cierta forma pueden usarse para indicarle a una herramienta que genere XML a partir de esos comentarios y de los elementos del código fuente que los preceden. Dichos comentarios son Single_Line_Comments (§6.3.3) que comienzan con tres barras (///
) o Delimited_Comments (§6.3.3) que comienzan con una barra y dos asteriscos(/**
). Deben colocarse inmediatamente antes de un tipo definido por el usuario o de un miembro al que hacen referencia. Las secciones de atributos (§22.3) se consideran parte de las declaraciones, por lo tanto, los comentarios de documentación deben preceder a los atributos aplicados a un tipo o miembro.
Con fines explicativos, el formato de los comentarios de documentación 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 particulares de las reglas léxicas Single_Line_Comment y 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 que sigue a los caracteres ///
en cada uno de los Single_Line_Doc_Comments adyacentes al Single_Line_Doc_Comment actual, entonces ese carácter de espacio en blanco no se incluye en la salida XML.
En un Delimited_Doc_Comment, si el primer carácter que no es unespacio en blanco en la segunda línea es un ASTERISCO y se repite el mismo patrón de caracteres opcionales de espacio en blanco seguido de un ASTERISCO al inicio de cada línea dentro del Delimited_Doc_Comment, entonces los caracteres de ese patrón repetido no se incluyen en la salida XML. El patrón puede incluir caracteres de espacio en blanco tanto después como antes del carácter ASTERISCO.
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 dentro de los comentarios de documentación debe tener el formato correcto según las reglas de XML (http://www.w3.org/TR/REC-xml). Si el XML no tiene el formato correcto, se genera una advertencia y el archivo de documentación incluirá un comentario en el que se indica que se detectó 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 una de estas etiquetas, el generador de documentación debe verificar que el parámetro especificado exista y que todos los parámetros estén descritos en los comentarios de documentación. Si esa verificación falla, 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 verificar que el elemento de código exista. Si la verificación falla, el generador de documentación emite una advertencia. Cuando busca un nombre descrito en un atributocref
, el generador de documentación debe respetar la visibilidad del espacio de nombres de acuerdo con las instrucciones de uso presentes en el código fuente. En los elementos de código genéricos, no se puede usar la sintaxis genérica normal (por ejemplo, “List<T>
”) porque produce un XML no válido. Se pueden usar llaves en lugar de corchetes (por ejemplo, “List{T}
”) o también se puede usar la sintaxis de escape de XML (por ejemplo, “List<T>
”).La etiqueta
<summary>
está destinada a ser usada por un visor de documentación para mostrar información adicional sobre un tipo o miembro.La etiqueta
<include>
agrega información desde un archivo XML externo.
Tenga en cuenta que el archivo de documentación no proporciona información completa sobre el tipo y sus miembros (por ejemplo, no contiene información sobre el tipo). Para obtener esa información sobre un tipo o miembro, debe usarse el archivo de documentación junto con la reflexión en el tipo o miembro.
Un tipo parcial o un método parcial puede declararse en varias partes, cada una de las cuales puede encontrarse en una o más unidades de compilación, y cada una puede tener uno o más comentarios de documentación. Un método parcial normalmente tiene una “declaración parcial de definición” y una “declaración parcial de implementación”.
Para un tipo parcial, los comentarios de documentación que se aplican directamente a ese tipo, si existen, de cada una de sus partes, se escriben todos en el archivo de documentación en un orden no especificado.
Para un método parcial:
- Si una declaración parcial de definición no tiene una declaración parcial de implementación correspondiente, se ignoran los comentarios de documentación de esa declaración de definición (ya que dicha declaración se eliminará).
- En caso contrario, si la declaración parcial de implementación tiene comentarios de documentación, se escriben en el archivo de documentación y se ignoran los comentarios de documentación de la declaración parcial de definición.
- En caso contrario, se escriben en el archivo de documentación los comentarios de documentación de la declaración parcial de definición.
D.3 Etiquetas recomendadas
D.3.1 Generalidades
El generador de documentación debe aceptar y procesar cualquier etiqueta que sea válida según las reglas de XML. Las etiquetas siguientes proporcionan funciones de uso general en la documentación de usuario. (Por supuesto, es posible usar otras etiquetas).
Etiqueta | Referencia | Propósito |
---|---|---|
<c> |
§D.3.2 | Aplica un estilo de fuente tipo código al texto |
<code> |
§D.3.3 | Presenta una o más líneas de código fuente o salida del programa |
<example> |
§D.3.4 | Indica un ejemplo |
<exception> |
§D.3.5 | Identifica las excepciones que un método puede lanzar |
<include> |
§D.3.6 | Agrega XML desde un archivo externo |
<list> |
§D.3.7 | Crea una lista o tabla |
<para> |
§D.3.8 | Permite agregar estructura al texto |
<param> |
§D.3.9 | Describe un parámetro de un método o constructor |
<paramref> |
§D.3.10 | Identifica que una palabra es el nombre de un parámetro |
<permission> |
§D.3.11 | Documenta la accesibilidad de seguridad de un miembro |
<remarks> |
§D.3.12 | Describe información adicional sobre un tipo |
<returns> |
§D.3.13 | Describe el valor devuelto por un método |
<see> |
§D.3.14 | Especifica un vínculo |
<seealso> |
§D.3.15 | Genera una entrada de Consulte también |
<summary> |
§D.3.16 | Describe un tipo o un miembro de un tipo |
<typeparam> |
§D.3.17 | Describe un parámetro de tipo para un tipo o método genérico |
<typeparamref> |
§D.3.18 | Identifica que una palabra es el nombre de un parámetro de tipo |
<value> |
§D.3.19 | Describe una propiedad |
D.3.2 <c>
Esta etiqueta proporciona un mecanismo para indicar que un fragmento de texto dentro de una descripción debe mostrarse con una fuente especial, como la que se usa para un bloque de código. Para líneas de código reales, use <code>
(§D.3.3).
Sintaxis:
<c>
texto</c>
Ejemplo:
/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
public class Point
{
}
D.3.3 <código>
Esta etiqueta se usa para mostrar una o más líneas de código fuente o salida del programa con una fuente especial. Para fragmentos pequeños de código dentro de un texto narrativo, 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)
{
...
}
}
D.3.4 <ejemplo>
Esta etiqueta permite incluir un código de ejemplo dentro de un comentario, con el fin de especificar cómo podría usarse un método u otro miembro de una biblioteca. Por lo general, también se utiliza la etiqueta <code>
(§D.3.3).
Sintaxis:
<example>
descripción</example>
Ejemplo:
Consulte la sección <code>
(§D.3.3) para ver un ejemplo.
Excepción D.3.5 <>
Esta etiqueta proporciona una forma de documentar las excepciones que un método puede lanzar.
Sintaxis:
<exception cref="
miembro">
descripción</exception>
donde
-
cref="
miembro"
es el nombre de un miembro. El generador de documentación verifica que el miembro especificado exista y convierte al miembro en el nombre de elemento canónico en el archivo de documentación. - descripción es una explicación de las circunstancias en las que se lanza 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 <incluir>
Esta etiqueta permite incluir información desde un documento XML externo al archivo de código fuente. El archivo externo debe ser un documento XML con formato correcto, y se aplica una expresión XPath a ese documento para especificar qué parte del XML incluir. La etiqueta <include>
se reemplaza por el XML seleccionado del documento externo.
Sintaxis:
<include file="
nombre de archivo" path="
xpath" />
donde
-
file="
nombre de archivo"
es el nombre del archivo XML externo. El nombre del archivo se interpreta en relación con el archivo que contiene la etiqueta. -
path="
xpath"
es una expresión XPath que selecciona parte del contenido XML del archivo XML externo.
Ejemplo:
Si el código fuente contiene una declaración como:
/// <include file="docs.xml" path='extradoc/class[@name="IntList"]/*' />
public class IntList { ... }
y el archivo externo “docs.xml” tiene 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>
entonces, se genera la misma documentación como si el código fuente contuviera directamente esa documentación:
/// <summary>
/// Contains a list of integers.
/// </summary>
public class IntList { ... }
D.3.7 <lista>
Esta etiqueta se usa para crear una lista o una tabla de elementos. Puede contener un bloque <listheader>
para definir la fila de encabezado de una tabla o una lista de definiciones. (Cuando se define una tabla, solo se debe proporcionar una entrada para término en el encabezado).
Cada elemento de la lista se especifica con un bloque <item>
. Al crear una lista de definiciones, se deben especificar tanto término como 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>
donde
- término es el término que se va a definir y cuya definición está en la descripción.
- descripción es un elemento de una lista con viñetas o numerada, 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 <párr>
Esta etiqueta se utiliza dentro de otras etiquetas, como <summary>
(§D.3.16) o <returns>
(§D.3.13), y permite agregar estructura al texto.
Sintaxis:
<para>
contenido</para>
donde
- contenido 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 <parámetro>
Esta etiqueta se usa para describir un parámetro de un método, constructor o indexador.
Sintaxis:
<param name="
nombre">
descripción</param>
donde
- nombre es el nombre del parámetro.
- descripción es una explicació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 una forma exclusiva.
Sintaxis:
<paramref name="
nombre"/>
donde
- nombre 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)
{
...
}
}
D.3.11 <permiso>
Esta etiqueta permite documentar la accesibilidad de seguridad de un miembro.
Sintaxis:
<permission cref="
miembro">
descripción</permission>
donde
- miembro es el nombre de un miembro. El generador de documentación verifica que el elemento de código especificado exista y convierte al miembro en el nombre de elemento canónico en el archivo de documentación.
- descripción es una explicación del acceso al miembro.
Ejemplo:
public class MyClass
{
/// <permission cref="System.Security.PermissionSet">
/// Everyone can access this method.
/// </permission>
public static void Test()
{
...
}
}
D.3.12 <observaciones>
Esta etiqueta se usa para especificar información adicional sobre un tipo. Use <summary>
(§D.3.16) para describir el tipo en sí y los miembros de un tipo.
Sintaxis:
<remarks>
descripción</remarks>
donde
- descripción es el texto de la observación.
Ejemplo:
/// <summary>
/// Class <c>Point</c> models a point in a two-dimensional plane.
/// </summary>
/// <remarks>
/// Uses polar coordinates
/// </remarks>
public class Point
{
...
}
D.3.13 <devoluciones>
Esta etiqueta se usa para describir el valor devuelto por un método.
Sintaxis:
<returns>
descripción</returns>
donde
- descripción es una explicación del valor de retorno.
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 <véase>
Esta etiqueta permite especificar un vínculo dentro del texto. Use <seealso>
(§D.3.15) para indicar el texto que debe aparecer en una subcláusula Véase también.
Sintaxis:
<see cref="
miembro" href="
url" langword="
palabra clave" />
donde
- miembro es el nombre de un miembro. El generador de documentación verifica que el elemento de código especificado exista y convierte el miembro en el nombre del elemento en el archivo de documentación generado.
- url es una referencia a una fuente externa.
- palabra clave es una palabra que debe resaltarse 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 <Véase también>
Esta etiqueta permite generar una entrada para la subcláusula Véase también. Use <see>
(§D.3.14) para especificar un vínculo dentro del texto.
Sintaxis:
<seealso cref="
miembro" href="
url" />
donde
- miembro es el nombre de un miembro. El generador de documentación verifica que el elemento de código especificado exista y convierte el miembro en el nombre del elemento en el archivo de documentación generado.
- url es una referencia a una fuente externa.
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)
{
...
}
}
D.3.16 <resumen>
Esta etiqueta puede usarse 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>
donde
- descripción 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 en un tipo o método genérico.
Sintaxis:
<typeparam name="
nombre">
descripción</typeparam>
donde
- nombre es el nombre del parámetro de tipo.
- descripción es una explicació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 mostrar este parámetro de tipo con un formato distintivo.
Sintaxis:
<typeparamref name="
nombre"/>
donde
- nombre 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)
{
...
}
}
D.3.19 <valor>
Esta etiqueta permite describir una propiedad.
Sintaxis:
<value>
descripción de la propiedad</value>
donde
- descripción de la propiedad es una explicació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 Generalidades
La siguiente información está destinada a implementaciones de C# dirigidas a la CLI.
El generador de documentación crea una cadena de identificador para cada elemento del código fuente que tenga un comentario de documentación. Esta cadena de identificador distingue de manera única a un elemento del código fuente. Un visor de documentación puede usar una cadena del identificador para distinguir el elemento correspondiente al que se aplica la documentación.
El archivo de documentación no representa jerárquicamente el código fuente; en cambio, presenta una lista plana con una cadena de identificador generada para cada elemento.
D.4.2 Formato de la cadena del identificador
El generador de documentación sigue las siguientes reglas al crear las cadenas de identificador:
No se coloca espacio en blanco en la cadena.
La primera parte de la cadena identifica el tipo de miembro documentado, mediante un carácter único seguido de dos puntos. Se definen los siguientes tipos de miembros:
Carácter Descripción E Evento F Campo M Método (incluye constructores, finalizadores y operadores) N Espacio de nombres P Propiedad (incluye indexadores) T Tipo (como 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 crea información de error para vínculos que no puede resolver. La segunda parte de la cadena es el nombre completamente calificado del elemento, que empieza 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 ya contiene puntos, estos se reemplazan por el carácter # (U+0023). (Se asume que ningún elemento contiene este carácter en su nombre). Los argumentos de tipo dentro del nombre completamente calificado, en los casos donde un miembro implementa explícitamente un miembro de una interfaz genérica, se codifican reemplazando los signos “
<
” y “>
>” por los caracteres “{
” y “}
”.En los métodos y propiedades con argumentos, la lista de argumentos aparece entre paréntesis. Si no tienen argumentos, se omiten los paréntesis. Los argumentos están separados por comas. La codificación de cada argumento es igual a una firma de CLI, como se detalla a continuación:
- Los argumentos se representan por su nombre de documentación, que deriva de su nombre completamente calificado, modificado de la siguiente forma:
- Los argumentos que representan tipos genéricos tienen un carácter “
'
” seguido del número de parámetros de tipo. - Los argumentos con los modificadores
in
,out
oref
llevan un@
después del nombre del tipo. Los argumentos pasados por valor o medianteparams
no llevan ninguna notación especial. - Los argumentos que son arreglos se representan como
[
lowerbound:
size,
…,
lowerbound:
size]
, donde la cantidad de comas indica el rango menos uno, y los límites inferiores y el tamaño de cada dimensión, si se conocen, se muestran en formato decimal. Si no se especifican un límite inferior ni un tamaño, se omiten. Si se omite tanto el límite inferior como el tamaño de una dimensión, también se omite el ":
" correspondiente. Los arreglos irregulares se representan con un “[]
” por cada nivel. Los arreglos unidimensionales omiten el límite inferior cuando este es 0 (el valor predeterminado) (§17.1). - Los argumentos que tienen tipos de puntero distintos de
void
se representan agregando un*
al nombre del tipo. Un punterovoid
se representa con un nombre de tipoSystem.Void
. - Los argumentos que hacen referencia a parámetros de tipo genérico definidos en tipos se codifican con 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 se codifican con dos comillas dobles “
``
” en lugar del “`
” que se usa para los tipos. - Los argumentos que hacen referencia a tipos genéricos construidos se codifican usando el tipo genérico, seguido de “
{
”, luego una lista separada por comas de los argumentos de tipo, y finalmente “}
”.
- Los argumentos que representan tipos genéricos tienen un carácter “
- Los argumentos se representan por su nombre de documentación, que deriva de su nombre completamente calificado, modificado de la siguiente forma:
D.4.3 Ejemplos de cadenas de identificador
Los siguientes ejemplos muestran fragmentos de código C# junto con la cadena de identificador generada para cada elemento del código fuente que puede tener un comentario de documentación:
Los tipos se representan con su nombre completamente calificado, acompañado de 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 completamente calificado.
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 funciones de operadores unarios utilizados es el siguiente: op_UnaryPlus
, op_UnaryNegation
, op_LogicalNot
, op_OnesComplement
, op_Increment
, op_Decrement
, op_True
y 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 funciones de operadores binarios utilizados es el siguiente: op_Addition
, op_Subtraction
, op_Multiply
, op_Division
, op_Modulus
, op_BitwiseAnd
, op_BitwiseOr
, op_ExclusiveOr
, op_LeftShift
, op_RightShift
, op_Equality
, op_Inequality
, op_LessThan
, op_LessThanOrEqual
, op_GreaterThan
y op_GreaterThanOrEqual
.
Los operadores de conversión tienen un sufijo “~
” seguido del tipo de retorno. Cuando el tipo de origen o destino de un operador de conversión es un tipo genérico, los caracteres “<
” y “">
” se reemplazan por “{
” 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
D.5.1 Código fuente en C#
En el ejemplo siguiente se muestra el código fuente de la 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
A continuación, se muestra la salida producida por un generador de documentación al procesar el código fuente de la clase Point
mostrada 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.
ECMA C# draft specification