[ Team LiB ] |
4.10 XML DocumentationC# offers three different styles of source-code documentation: single-line comments, multiline comments, and documentation comments. 4.10.1 C/C++-Style CommentsSingle- 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 types. Consequently, it cannot 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. 4.10.2 Documentation CommentsDocumentation comments are composed of embedded XML tags. These tags allow one to mark up the descriptive text to better define the semantics of the type or member, and also to incorporate cross-references. Documentation comments must either start with /// (that's three slashes), or (as of Visual C# 2003) be contained in multiline comments (that's /* ... */). They can be applied to any user-defined type or member. 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 XSLT, generating HTML documentation. Here is an example of documentation comments for a very 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"); } } 4.10.3 XML Documentation FilesWhen run through the compiler using the /doc:<filename> command-line option, the following 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 this type lives in. Every member that was 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 that were embedded in the documentation comments are also included in the XML file, and 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. 4.10.4 Predefined XML TagsThe predefined set of XML tags that can be used to mark up the descriptive text are listed here:
4.10.5 User-Defined TagsThere 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 (in which it verifies the parameter name and that all the parameters on the method are documented) and the cref attribute (in which 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. 4.10.6 Generated DocumentationOnce an XML file is generated from documentation comments, it typically requires another step before becoming generally useful to programmers, since most of us aren't quite able to parse and use an XML file "in the raw." The most common approach is to run the XML output through an XSLT stylesheet to generate some more human-friendly format, such as HTML. (Variations on this idea include generating PDF, RTF, or even Microsoft Word documents.) While Microsoft may publish a standardized XSLT file for this, companies may want to create their own to establish their own "look" for documentation of components they sell. Alternatively, several open source projects have already begun to explore this area, and produce neatly formatted documentation files; one example is http://ndoc.sourceforge.net. The ability to put user-defined tags into the XML documentation sections represents a powerful extensibility point—for example, a company may put implementation details about the method or class inside of <implementation> tags and define two XSLT files: one excluding the implementation tags, and the other including it. The non-<implementation>-aware files can be distributed publicly, while the <implementation>-aware files are used internally by developers. An automated test tool might run tests against those methods or classes described by a <test name=test-to-run> tag. Types meant to be stored in the database might use XML documentation tags to indicate the SQL required to create the tables, and a custom tool could be written to extract the necessary SQL from the XML documentation files in order to run it. Non-public information about the code can be embedded within the code itself or in the documentation comments and processed by an external tool via this mechanism, which makes it quite powerful. 4.10.7 Type or Member Cross-ReferencesType 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 4-4 lists the set of type or member prefixes.
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[ ] 1, 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( ) {...} } } |
[ Team LiB ] |