only for RuBoard - do not distribute or recompile |
C# offers three different styles of source code documentation: single-line comments, multiline comments, and documentation comments.
Single- and multiline comments use the C++ syntax: // and /*...*/:
int x = 3; // this is a comment MyMethod( ); /* this is a comment that spans two lines */
The disadvantage of this style of commenting is that there is no predetermined standard for documenting your types. Consequently, it can't be easily parsed to automate the production of documentation. C# improves on this by allowing you to embed documentation comments in the source and by providing an automated mechanism for extracting and validating documentation at compile time.
Documentation comments are similar to C# single-line comments but start with /// and can be applied to any user-defined type or member. These comments can include embedded XML tags as well as descriptive text. These tags allow you to mark up the descriptive text to better define the semantics of the type or member and also to incorporate cross-references.
These comments can then be extracted at compile time into a separate output file containing the documentation. The compiler validates the comments for internal consistency, expands cross-references into fully qualified type IDs, and outputs a well-formed XML file. Further processing is left up to you, although a common next step is to run the XML through an XSL/T, generating HTML documentation.
Here is an example documentation for a simple type:
// Filename: DocTest.cs using System; class MyClass { /// <summary> /// The Foo method is called from /// <see cref="Main">Main</see> /// </summary> /// <mytag>Secret stuff</mytag> /// <param name="s">Description for s</param> static void Foo(string s) { Console.WriteLine(s); } static void Main( ) { Foo("42"); } }
When the preceding source file is run through the compiler with the /doc:<filename> command-line options, this XML file is generated:
<?xml version="1.0"?> <doc> <assembly> <name>DocTest</name> </assembly> <members> <member name="M:MyClass.Foo(System.String)"> <summary> The Foo method is called from <see cref="M:MyClass.Main">Main</see> </summary> <mytag>Secret stuff</mytag> <param name="s">Description for s</param> </member> </members> </doc>
The <?xml...>, <doc>, and <members> tags are generated automatically and form the skeleton for the XML file. The <assembly> and <name> tags indicate the assembly that this type lives in. Every member preceded by a documentation comment is included in the XML file via a <member> tag with a name attribute that identifies the member. Note that the cref attribute in the <see> tag has also been expanded to refer to a fully qualified type and member. The predefined XML documentation tags embedded in the documentation comments are also included in the XML file. The tags have been validated to ensure that all parameters are documented, that the names are accurate, and that any cross-references to other types or members can be resolved. Finally, any additional user-defined tags are transferred verbatim.
This section lists the predefined set of XML tags that can be used to mark up the descriptive text:
<summary>description</summary> <remarks>description</remarks>
These tags describe a type or member. Typically, <summary>contains the description of a member, and <remarks> contains a full description of a type.
<param name="name">description</param>
This tag describes a parameter on a method. The name attribute is mandatory and must refer to a parameter on the method. If this tag is applied to any parameter on a method, all parameters on that method must be documented. You must enclose name in double quotation marks ("").
<returns>description</returns>
This tag describes the return values for a method.
<exception [cref="type"]>description</exception>
This tag describes the exceptions a method may throw. If present, the optional cref attribute should refer to the type of exception. You must enclose the type name in double quotation marks ("").
<permission [cref="type"]>description</permission>
This tag describes the permission requirements for a type or member. If present, the optional cref attribute should refer to the type that represents the permission set required by the member, although the compiler doesn't validate this. You must enclose the type name in double quotation marks ("").
<example>description</example> <c>code</c> <code>code</code>
These tags provide a description and sample source code explaining the use of a type or member. Typically, the <example> tag provides the description and contains the <c> and <code> tags, although these can also be used independently. If you need to include an inline code snippet, use the <c> tag. If you need to include multiline snippets, use the <code> tag.
<see cref="member">text</see> <seealso cref="member">text</seealso>
These tags identify cross-references in the documentation to other types or members. Typically, the <see> tag is used inline within a description, while the <seealso> tag is broken out into a separate "See Also" section. These tags are useful because they allow tools to generate cross-references, indexes, and hyperlinked views of the documentation. Member names must be enclosed by double quotation marks ("").
<value>description</value>
This tag describes a property on a class.
<paramref name="name"/>
This tag identifies the use of a parameter name within descriptive text, such as <remarks> or <summary>. The name must be enclosed by double quotation marks ("").
<list type=[ bullet| number| table]> <listheader> <term>name</term> <description>description</description> </listheader> <item> <term>name</term> <description>description</description> </item> </list> <para>text</para>
These tags provide hints to documentation generators on how to format the documentation.
<include file='filename' path='path-to-element'>
This tag specirfies an external file that contains documentation and an XPath path to a specific element in that file. For example, a path of docs[@id="001"]/* would retrieve whatever is inside of <docs id="001"/>. The filename and path must be enclosed by single quotation marks ('').
There is little that is special about the predefined XML tags recognized by the C# compiler, and you are free to define your own. The only special processing done by the compiler is on the <param> tag (where it verifies the parameter name and confirms that all the parameters on the method are documented) and the cref attribute (where it verifies that the attribute refers to a real type or member and expands it to a fully qualified type or member ID). The cref attribute can also be used in your own tags and is verified and expanded just as it is in the predefined <exception>, <permission>, <see>, and <seealso> tags.
Type names and type or member cross-references are translated into IDs that uniquely define the type or member. These names are composed of a prefix that defines what the ID represents and a signature of the type or member. Table 2-5 lists the set of type and member prefixes.
Prefix |
Applied to |
---|---|
N |
Namespace |
T |
Type (class, struct, enum, interface, delegate) |
F |
Field |
P |
Property (includes indexers) |
M |
Method (includes special methods) |
E |
Event |
! |
Error |
The rules describing how the signatures are generated are well-documented, although fairly complex.
Here is an example of a type and the IDs that are generated:
// Namespaces do not have independent signatures namespace NS { // T:NS.MyClass class MyClass { // F:NS.MyClass.aField string aField; // P:NS.MyClass.aProperty short aProperty {get {...} set {...}} // T:NS.MyClass.NestedType class NestedType {...}; // M:NS.MyClass.X( ) void X( ) {...} // M:NS.MyClass.Y(System.Int32,System.Double@,System.Decimal@) void Y(int p1, ref double p2, out decimal p3) {...} // M:NS.MyClass.Z(System.Char[],System.Single[0:,0:]) void Z(char[] p1, float[,] p2) {...} // M:NS.MyClass.op_Addition(NS.MyClass,NS.MyClass) public static MyClass operator+(MyClass c1, MyClass c2) {...} // M:NS.MyClass.op_Implicit(NS.MyClass)~System.Int32 public static implicit operator int(MyClass c) {...} // M:NS.MyClass.#ctor MyClass( ) {...} // M:NS.MyClass.Finalize ~MyClass( ) {...} // M:NS.MyClass.#cctor static MyClass( ) {...} } }
only for RuBoard - do not distribute or recompile |