Anson Horton, C# Compiler Program Manager
C# supports the creation of XML Comments, allowing developers to quickly annotate and document their source code without having to resort to clumsy and inconsistently formatted external files.
Introduction
XML Comments, preceded by a triple-slash (///), are a form of XML used for documentation. The tags used in the comments are completely customizable; however, there are a set of tags that have been agreed on by ECMA. The recommended tag set has special meanings for the C# compiler and the Visual Studio IDE, but developers may extend the recommended set to enforce corporate documentation standards, provide consistent formatting options to teams of developers, or add any additional information that they deem necessary. The only constraint on XML Comments is that the XML placed within the tags must be well-formed. This is enforced by the C# compiler as part of the compilation process.
Using XML Comments
C# developers may use XML Comments to document code on user-defined types, including classes, delegates, enums, and structs. In addition, XML Comments may be placed on members, including fields, events, properties, indexers, and methods. However, XML Comments are currently not supported for documenting namespaces.
XML Comments and Visual Studio .NET
Visual Studio .NET automatically recognizes and uses the recommended set of tags for constructing its own IntelliSense documentation. The three most important recommended tags are ,
In addition, the attribute cref can be added to a subset of the XML tags (see tags section for specifics), and the C# compiler will then resolve it against your code. This tag allows a comment to reference a code element elsewhere in source.
Creating a Documented Component
Developers will often be tasked with creating components for consumption by other developers on a team or organization. Adding documentation to the component helps clarify how and when to use the component and reduces overall support costs. Creating a documented component involves several steps:
1. Create the component
2. Create the XML file
3. Test the component in a deployment scenario
Step 1, create the component
This step may sound daunting at first, perhaps a bit like reading “remove roof, set aside” as step 1 on the instructions for remodeling your house. However, the actual creation of components is well documented in several walkthroughs available in the MSDN Library & VS documentation; therefore, we won’t focus our attention on it here, but instead use a simple example and use it to show how to add XML documentation.
The eventual goal of this step-by-step tutorial is to ship two files. The first is a .DLL that the component consumer will reference; the second is an .XML file that contains all of the documentation for that component. The skeleton for a sample component follows:
using System;
namespace XMLDeploy1
{
public class Temperature
{
public static int CelsiusToFahrenheit(int degreesCelsius)
{
return ((int)((9/5)*degreesCelsius) + 32);
}
public static int FahrenheitToCelsius(int degressFahrenheit)
{
return ((int)((5/9)*(degressFahrenheit - 32)));
}
}
}
Notice that the component is missing a very important piece – documentation! Despite the component being relatively simple, there are 3 places where added documentation will help the consumer of the component tremendously. Those 3 places are class level documentation, method level documentation, and parameter level documentation.
In order to add class level documentation, type /// on the line above public class Temperature. Then in-between the automatically generated summary tags type a description of what class Temperature is meant to be used for. For example:
///
/// Class temperature provides functions which convert among various
/// temperature scales.
///
public class Temperature
Method and parameter level documentation are attached to a given method, much like the documentation we just added was attached to the class. For example, lets add comments to the method public static int CelsiusToFahrenheit(int degreesCelsius). Type /// before the method declaration, notice that three tags have been automatically generated and inserted into the source. The first,
///
/// Converts degrees Celsius to degrees Fahrenheit
///
/// Degrees Celsius
///
public static int CelsiusToFahrenheit(int degreesCelsius)
After the same steps for method and parameter level documentation are applied to the second method in the class, our example looks like this:
using System;
namespace XMLDeploy1
{
///
/// Class temperature provides functions which convert among various
/// temperature scales.
///
public class Temperature
{
///
/// Converts degrees Celsius to degrees Fahrenheit
///
/// Degrees Celsius
///
public static int CelsiusToFahrenheit(int degreesCelsius)
{
return ((int)((9/5)*degreesCelsius) + 32);
}
///
/// Converts degrees Fahrenheit to degrees Celsius
///
/// Degrees Fahrenheit
///
public static int FahrenheitToCelsius(int degressFahrenheit)
{
return ((int)((5/9)*(degressFahrenheit - 32)));
}
}
}
Step 2, create the XML file
Now that the component is built with all the comments littered throughout, it’s time to generate an .XML file that contains all of the documentation information. IntelliSense will use this file to generate ToolTips for the component.
In order to create the XML file, go to the “Solution Explorer”, right-click on the project, and select “Properties”. In the resulting dialog box, select “Build” under the “Configuration Properties” folder.
Notice the “XML Documentation File” property. Enter the name of the .XML file to be generated. Note: this name must be the same as the .DLL name or IntelliSense will not be able to find it.
Rebuild the application.
Step 3, test the component in a deployment scenario
Create a new project in order to test the newly created XML Comment-enabled component. After creating the project go to the ‘add references’ dialog by right-clicking the project in solution explorer and selecting ‘add reference’ from the context menu. Click on the ‘browse’ button and find the.DLL of the component we just created. Select this file and click okay. These steps will add a reference from your test project to the component created in step 1. When the reference is added a copy of both the .DLL and the .XML file are copied to the “bin” directory of the test application (the .XML file and the .DLL must live in the same directory, or only the .DLL will be copied). IntelliSense will now parse the XML file and give the consumer ToolTips when it is being used:
Likewise, the VS ObjectBrowser will now be able to see the component and associated documentation:
Tag Reference
The recommended XML tags follow:
Tag Purpose
Set one or more lines of source code or program output
Indicate an example
Identifies the exceptions a method can throw
Create a list or table
Permit structure to be added to text
Describe a parameter for a method or constructor
Identify that a word is a parameter name
Document the security accessibility of a member
Describe a type
Describe the return value of a method
Specify a link
Generate a See Also entry
Describe a member of a type
Describe a property
Tag:
This tag provides a mechanism to indicate that a fragment of text within a description should be set a special font such as that used for a block of code. (For lines of actual code, use )
Syntax:
text to be set like code
Example:
/// Class Point models a point in a two-d
/// plane.
public class Point
{
// …
}
Tag:
This tag is used to set one or more lines of source code or program output in some special font. (For small code fragments in narrative, use .)
Syntax:
source code or program output
Example:
/// This method changes the point's location by
/// the given x- and y-offsets.
/// For example:
///
/// Point p = new Point(3,5);
/// p.Translate(-1,3);
///
/// results in p 's having the value (2,8).
///
///
public void Translate(int xor, int yor)
{
X += xor;
Y += yor;
}
Tag:
This tag allows example code within a comment, to specify how a method or other library member may be used. Ordinarily, this would also involve use of the tag as well.
Syntax:
description
Example:
See for an example.
Tag:
This tag provides a way to document the exceptions a method can throw.
Syntax:
description
cref="member" – The name of a member. The documentation generator checks that the given member exists and translates member to the canonical element name in the documentation file.
description – A description of the circumstances in which the exception is thrown.
Example:
public class DataBaseOperations
{
///
///
///
///
public static void ReadRecord(int flag)
{
if (flag == 1)
throw new MasterFileFormatCorruptException();
else if (flag == 2)
throw new MasterFileLockedOpenException();
// …
}
}
Tag:
This tag is used to create a list or table of items. It may contain a block to define the heading row of either a table or definition list. (When defining a table, only an entry for term in the heading need be supplied.)
Each item in the list is specified with an - block. When creating a definition list, both term and description must be specified. However, for a table, bulleted list, or numbered list, only description need be specified.
Syntax:
term
description
term
description
…
term
description
term - The term to define.
description - The definition of the term.
Either an item in a bullet or numbered list, or the definition of a term.
Example:
public class MyClass
{
/// Here is an example of a bulleted list:
///
///
/// Item 1.
///
///
/// Item 2.
///
///
///
public static void Main ()
{
// …
}
}
Tag:
This tag is for use inside other tags, such as or , and permits structure to be added to text.
Syntax:
content
content - The text of the paragraph.
Example:
/// This is the entry point of the Point class
/// testing program.
/// This program tests each method and operator,
/// and is intended to be run after any non-trvial
/// maintenance has been performed on the Point
/// class.
public static void Main()
{
// …
}
Tag:
This tag is used to describe a parameter for a method, constructor, or indexer.
Syntax:
description
name - The name of the parameter.
description - A description of the parameter.
Example:
/// This method changes the point's location to
/// the given coordinates.
/// xor is the new x-coordinate.
/// yor is the new y-coordinate.
public void Move(int xor, int yor)
{
X = xor;
Y = yor;
}
Tag:
This tag is used to indicate that a word is a parameter. The documentation file can be processed to format this parameter in some distinct way.
Syntax:
name - The name of the parameter.
Example:
/// This constructor initializes the new Point to
/// ( ,
/// ).
/// xor is the new Point's x-
/// coordinate.
/// yor is the new Point's y-
/// coordinate.
public Point(int xor, int yor)
{
X = xor;
Y = yor;
}
Tag:
This tag allows the security accessibility of a member to be documented.
Syntax:
description
cref="member" - The name of a member. The documentation generator checks that the given code element exists and translates member to the canonical element name in the documentation file.
description - A description of the access to the member.
Example:
/// Everyone can
/// access this method.
public static void Test()
{
// …
}
Tag:
This tag is used to specify overview information about a type. (Use to describe the members of a type.)
Syntax:
description
description - The text of the remarks.
Example:
/// Class Point models a point in a two-dimensional
/// plane.
public class Point
{
// …
}
Tag:
This tag is used to describe the return value of a method.
Syntax:
description
description - A description of the return value.
Example:
/// Report a point's location as a string.
/// A string representing a point's location, in the form
/// (x,y), without any leading, training, or embedded
/// whitespace.
public override string ToString()
{
return "(" + X + "," + Y + ")";
}
Tag:
This tag allows a link to be specified within text. (Use to indicate text that is to appear in a See Also section.)
Syntax:
cref="member" - The name of a member. The documentation generator checks that the given code element exists and passes member to the element name in the documentation file.
Example:
/// This method changes the point's location to
/// the given coordinates.
///
public void Move(int xor, int yor)
{
X = xor;
Y = yor;
}
/// This method changes the point's location by
/// the given x- and y-offsets.
///
///
public void Translate(int xor, int yor)
{
X += xor;
Y += yor;
}
Tag:
This tag allows an entry to be generated for the See Also section. (Use to specify a link from within text.)
Syntax:
cref="member" - The name of a member. The documentation generator checks that the given code element exists and passes member to the element name in the documentation file.
Example:
/// This method determines whether two Points have the /// same location.
///
///
public override bool Equals(object o)
{
// …
}
Tag:
This tag can be used to describe a member for a type. (Use to describe the type itself.)
Syntax:
description
description - A summary of the member.
Example:
/// This constructor initializes the new Point to
/// (0,0).
public Point() : this(0,0)
{
}
Tag:
This tag allows a property to be described.
Syntax:
property description
property description - A description for the property.
Example:
/// Property X represents the point's x-
/// coordinate.
public int X
{
get { return x; }
set { x = value; }
}