C# XML documentation comments FAQ


Ever since we released the first version of C# 1.0 I’ve received a question or two a month about XML documentation comments.  These are often referred to as ‘doc comments’ for short.  The questions range from the use of doc comments in VS to the recommended schema of the XML.  This post captures a few of the common questions that I’ve seen.

Why isn’t there a multi-line version of XML doc comments?

There are actually two forms of doc comments in C#, single and multi-line.  However, the single-line version is by far the most commonly used; in fact, the multi-line version wasn’t supported until the 1.1 version of the compiler even though they were defined in the 1.0 version of the language spec.  The single line version is likely to be familiar to any user of Visual Studio; it’s syntactically indicated on a line that starts with a triple slash (///):

        /// <summary>

        /// This is the single line version of the doc comment
        /// </summary>

        static void Example()
        {
        }
 

The multi-line version uses /**:

        /** <summary>
         * This is the multi-line version

         * </summary> */
        static void Example()

        {

        }

 

They are functionally identical, the only difference being that it’s possible to use the multi-line version “inline” within an expression.  The multi-line version of the comments weren’t actually in the proposed version of the language specification submitted to ECMA; however, the ECMA committee decided that having both forms would be better.

The C# language service doesn’t support multi-line XML doc comments as well as the singe line comments (i.e. /** doesn’t auto-generate any tags); however, colorization for multi-line doc comments does work, and in VS 2005 it’s possible to get completion lists for the tags but you must first end the multi-line comment and then go back and enter in the tags.

How do I make VS show the XML doc comments of the types and methods of my components in completion lists and object browser?

This has been an extremely common question for a long time.  The short and long of it is that you must deploy the XML file that is generated by the compiler with the component.  They must be in the same directory, and the XML file must have the same name as the component except with an .xml extension.  I wrote a whitepaper that contains a walkthrough, in VS 2003, which demonstrates this.  It’s available here.

How do use XML doc comments to refer to generic types?

Several of the tags that are recommended in the C# language specification have an attribute named ‘cref’ on them.  Cref refers to a code reference.  This attribute can be used by tools to create links between different types and members (e.g. object browser uses crefs to create hyperlinks that allow quick navigation to the related type).  The C# compiler actually understands the cref attribute to a limited extent.  The compiler will try to bind the type or member listed in a cref attribute to a code element defined your source.  Assuming that it can it will then fully qualify that member in the generated XML file.  For example:

using System.Collections;

class Program

{

    /// <summary>

    /// DoSomething takes a <see cref=”ArrayList”/>

    /// </summary>

    void DoSomething(ArrayList al) { }

}

This generates the following XML file:

        <member name=M:Program.DoSomething(System.Collections.ArrayList)>

            <summary>

            DoSomething takes a <see cref=T:System.Collections.ArrayList/>

            </summary>

        </member>

Notice that the compiler bound ArrayList and emitted System.Collections.ArrayList instead.

I’m sure you’re saying, wow, fascinating, um… but what does that have to do with generics?  Good question.  Generics complicate doc comments because C# uses angle brackets which would usually be associated with XML.  It’s possible just to use the normal escaping mechanisms associated with angle brackets (&gt; &lt) in XML.  Unfortunately this turns out to look fairly ugly:

using System.Collections.Generic;

class Program

{

    /// <summary>

    /// DoSomething takes a <see cref=”List&lt;T>”/>

    /// </summary>

    void DoSomething(List<int> al) { }

}

This can become particularly onerous when the generic type has many type arguments.  The compiler team decided to improve this by allowing an alternate syntax to refer to generic types and methods in doc comments.  Specifically, instead of using the open and close angle-brackets it’s legal to use the open and close curly braces.  The example above would then become:

using System.Collections.Generic;

class Program

{

    /// <summary>

    /// DoSomething takes a <see cref=”List{T}”/>

    /// </summary>

    void DoSomething(List<int> al) { }

}

 

The compiler understands this syntax and will correctly bind List{T} to System.Collections.Generic.List<T>. 

When the <example> tag is used and there are a number of generic types or methods in the example, an easier approach is to simply surround the example with a CDATA block.  That way there is no need to escape less-than signs.

Which doc comment tags are understood and used by Visual Studio?

There are a number of tags that Visual Studio uses to process or present information:

Tag name

Tools that make use of the tag

summary

Completion lists, quick info, class view, class designer, object browser, object test bench

param

Parameter help, quick info, object test bench, class designer, object browser

exception

Completion lists, quick info, object browser

include

C# Compiler

returns

Object browser

see/seealso

Object browser

 

The ‘metadata as source’ feature, which is invoked when goto definition is performed on a type or member that is defined in metadata, processes a number of the tags documented in the C# language specification and tries to provide a reasonable view.

How do I generate HTML or .chm documentation from the XML file?

The generated XML file actually doesn’t contain enough information to fully generate good reference documentation.  In fact, it was an explicit goal to make the XML file contain just enough information to map the comment back to the associated code element in metadata.  Regardless, there are a number of tools that take the assembly and the generated XML file and produce a very nice looking, easy to browse output.  NDoc has been a favorite of many developers that I’ve talked to for quite a while.  I believe that development on NDoc has slowed somewhat; another option is SandCastle.


Comments (39)

  1. Anonymous says:

    Creating a .CHM file or other type of documentation file from the XML comments is an important feature with a lot of demand around it (just look at the number of downloads nDoc gets). Having more verbose comments ala GhostDoc is also something that is highly useful.

    Being able to keep the documentation and the code in the same document (the .cs file) makes it far more likely that the documentation will actually stay up to date.

    The XML comments feature should be expanded to include images, samples, and other expository text.

    Response

    I agree with your suggestions and we’re tracking them on a potential features list for a future version of VS.

  2. Anonymous says:

    Greate post, thanks a lot! I just translated it to Russian and want to publish it on famous Russian programmer’s site/forum http://rsdn.ru/ (“Russian Software Developers Network”). Can you grant me your permission to this? Of course, your copyright will be saved with the translated version of the article.

    Response

    Sure! I’ve got no problem with any of these posts being translated into other languages. Thanks for taking the time to do so 🙂

  3. Anonymous says:

    This week you can watch the first in a series of videos featuring members of the Microsoft C# team. A video of Raj Pai, the Group Program Manager for the C# team, leads off the series.

  4. Anonymous says:

    Unfortunately there is no way of reflection on the comments as far as I know…

  5. nzeemin says:

    So, here is Russian-translated version of the post: http://rsdn.ru/article/devtools/CSxmlcmnt.xml

    Response

    Awesome! Thanks!

  6. Anonymous says:

    Has there been any consideration of providing a step in the compilation process that would inject documentation comments into an assembly, thus making it possible to discover documentation comments via reflection? This could easily be accomplished via attributes and it would be quite useful to tool developers. It would also make an assembly “self-documenting” without having to worry about toting around an additional *.xml file

    Response

    Good question. Honestly the choice to split the documentation and the metadata/il was intentional. There are a few reasons. The first is that the documentation is really useful only when developing an application, which tends to be a comparitvely small amount of the time as compared to its usage in running the application. That wouldn’t make much of a difference if it were free to make use of attributes; however, there is a cost both in the size of the assembly and the load time. So, we decided to split it out such that a fairly trimed down version could be deployed to end users with the documentation being deployed separately to developers.

    I generally think this was the right choice; however, I definitely agree that we should have and promote and easy way to access doc comment information. It sounds like an interesting topic for a future blog.

  7. Anonymous says:

    I have been struggling with this issue for a few weeks now. How to I put crefs into my C# doc comments…

  8. Anonymous says:

    Learn Videos and Presentations The LINQ Framework: What’s New in the May CTP Anders: Chatting about LINQ

  9. Anonymous says:

    One of your examples has a comment stating ‘DoSomething takes a <see cref="List{T}"/>’.

    In fact DoSomething takes a List<int>, not just any List<T>.  Is there a way to specify this constraint in the XML comments?

  10. Anonymous says:

    Yes! Yes! Yes!

    I totally agree with the comment above by Chris (not me, the other Chris) that there should be an option to embed documentation comments into an assembly. I spent days writing a unified reflection model (an Assembly DOM, if you will) that provided the documentation comments for a given type, method, etc. I work a lot with reflection and many, many times I have needed this information.

    How lovely it would be to write:

    DocComments comments = typeof(MyType).DocComments.

    !!!!

  11. Anonymous says:

    I’m sorry, but…  the last post, and the other referencing the whole "reflection of comments" is nothing short of laughable.

    I don’t mean to be rude, but you guys do realize that when something is COMPILED that the comments are considered whitespace, right?  And that when they’re stripped, they’re stored in an .xml comments file (if specified).

    The latter request is just about as a horrible idea as any.  I don’t know about you, but no developer worth their weight in salt (or gold) would ever want the comments compiled in to their assembly, not any part.  If you -really- want this, look at doing something msbuild and resources…  don’t, don’t, don’t ask anyone on any team even remotely close to the .NET Framework to add such a feature.

    This is a request that I can only assume is being made by people that really don’t have a clue how something compiles, or aren’t just thinking this through.  

    How ’bout you guys look up the comments from the xml markup during the reflection process?  Is it really that hard?

    The response to the first post obviously shows that they were thinking this through.  At least someone over there is.  😉

  12. akashelkar says:

    Is there a way I can generate the code comments back from an XML document?  For e.g. if I have a code module in which I have added "doc comments" at various places and I generate an XML file from these comments.  Can I have an XML file made in the same format and then reverse-engineer it somehow to get the comments underlying it?

    If this were possible, I could create my functional/technical specs in the XML format and then reverse-enginner it to have the specs entered into an existing or a blank code file as comments.  Easy reference when writing code!

  13. Anonymous says:

    It would be great if there was any guideline on writing the <exception> documentation tags.

    The .NET Framework Guidelines book gives plenty of guidelines on using exceptions, but nothing about documenting exceptions thrown by a method.

    I fully agree and support that the exception specification is not part of the C# language, but documenting what exceptions are thrown by a method in a public API is an entirely different thing and I think it must be done. The .NET Framework itself documents thrown exceptions thoroughly.

    I’m a lead developer of a popular commercial component and we were not documenting thrown exceptions, but the users ask for this and we must formulate a strategy.

    The question is basically is:

    I have a public API method A which calls heaps of internal methods and heaps of .NET framework methods and classes.

    What <exception> documentation should I include in the documentation of the method A?

    a. Should I document only exceptions thrown explicitly by method A?

    b. Should I document ALL possible exceptions that can be thrown by method A and ANY method that it calls?

    If I do "a", then it is easy to mislead the users by "underdocumentation". For example I have a public method Load that does something simple and calls the more meaty internal method LoadCore. It makes no sense to document exceptions thrown only by the Load method since there are none. Then I must do "b".

    However, it is very hard to do "b" properly because it requires a lot of maintenance! Basically it means the documentation for exceptions for a public method will depend on the actual implementation that could be deep down. For example, I changed the implementation of the Load method to use different .NET methods and classes and they throw different exceptions now. I should then manually find and update all exception documentation that could be affected!!!

    So I think I will stick with NO <exception> documentation for the time being.

    Thanks.

  14. Anonymous says:

    In addition to my previous comment about <exception> documentation I would like to say that creating some sort of an automatic tool that will follow the call tree from the public method A into all internals to collect documentation for all thrown exceptions is not going to solve the problem.

    For example, deep in my code I access an element of some internal array. You know this can thrown IndexOutOfRangeException, but hopefully, I wrote stable code that will not do such thing. Therefore, I expect that IndexOutOfRangeException will never be thrown and I certainly don’t want to document it in the public API.

    So it looks like there is no escape from the hard work in this case? How you did this for MSDN at Microsoft?

  15. Anonymous says:

    Hi!

    How I can add some contents to the documentation without  a class definition? For example:

    Introduccion

       What’s new

       Bugs

    Abstract

       Bla, bla..

  16. Anonymous says:

    On personal opinion, I find this very helpful.

    Guys, I have also posted some more relevant info further on this, not sure if you find it useful: http://www.bidmaxhost.com/forum/

  17. Anonymous says:

    What is your opinion about documenting overriden methods in c# code ?

    What is the best practice for this and what are the consequencies in the final documentation ?

  18. Anonymous says:

    CHM Documents are nice, but with a little photoshop skill, and a XSL sheet you can create essentially the same thing. Using CSS positioning or frames to create a TOC and automatic linking throughout the document.

    You can even link back to parent or related classes, link through the <seealso> tag,etc.

    It took me about a day of work to make a nice XSL file that will last me for the entirety I use .NET.

    …And you dont have to worry about NDoc.

  19. Allann says:

    Hi,

    This might be a little of topic, but how do you specify a code segment enclosed in the <code> tags as being a specific language so that the laguage filter will work?

    Thanks in advance

    Allan

  20. Anonymous says:

    What about alias ?

    Can we use them is cref ?

    Using MyCtrl = MyNamespace.Controls;

    class Program

    {

       /// <summary>

       /// DoSomething takes a <see cref="MyCtrl.MyControl>"/>

       /// </summary>

       void DoSomething(MyCtrl.MyControl control) { }

    }

  21. Anonymous says:

    I agree with Anson. The separation makes a lot of sense. I still come from the belief that wasting space is a bad idea, no matter how trivial it seems. Maybe the reflection API’s could be added, but rather than embedding the docs, they would look for the associated XML doccomments files. Many tools I find now are coming with the compiled xml.

  22. Anonymous says:

    how to create xml comment file of website to provide as input to sandcastle

  23. Ignaz says:

    Is there a way to extract the XML doc comments for public members only? I use the same commenting style for internal and private members, but don’t want to deploy those comments.

  24. Anonymous says:

    How to type character < less than in XML comment ?

  25. Anonymous says:

    In Visual Studio 2005, whenever I try to put a less than sign (left angle bracket) after n"/// " (space after third slash), the IDE hangs.  I hold shift then hit < and I never get control back. Is this a known bug, I could not find any reference to it on the web.

  26. Anonymous says:

    Hi there, thanks for the informative article. You talk about making cross references to generic types, eg:

    /// <summary>

    /// Populates the <see cref="Stack{int}"/>.

    /// </summary>

    So here we have defined a cref to a generic stack of ints. The type information has been put in braces instead of <> and VS recognises this correctly. However, what if the contained type is generic itself? I would have guessed that the following should work:

    /// <summary>

    /// Populates the <see cref="Stack{List{int}}"/>.

    /// </summary>

    The type referenced above is a generic stack that contains a generic list of ints. It is a perfectly valid construct yet the brace syntax demonstrated above does not work. It results in an unresolved reference to Stack<List<int>>, even though the referenced types are in the current compilation scope. It would appear that the brace syntax only works for generic types that are ‘one level deep’ as it were.

    So please, how would you make a cross reference to a generic type that contains a generic type, such as in the above example?

    Thank you for your time.

  27. Anonymous says:

    ".. there should be an option to embed documentation comments into an assembly. How lovely it would be to write:

    DocComments comments = typeof(MyType).DocComments."

    I have written a small class library called DocsByReflection that doesn’t embed the comments into assembly but does provide a simple way to get the information from the XML, in a similar way to how you have described.

    I hope some find it useful, it is documented here:

    http://jimblackler.net/blog/?p=49

  28. Anonymous says:

    Hi,

    This week you can watch the first in a series of videos featuring members of the Microsoft C# team. A video of Raj Pai, the Group Program Manager for the C# team, leads off the series.

    thanks.

  29. Anonymous says:

    Learn Videos and Presentations The LINQ Framework: What’s New in the May CTP Anders: Chatting about LINQ

  30. Anonymous says:

    GhostDoc has generated the following for me:

    <see cref="System.String[]"/>

    The compiler warns me that this is not syntactically correct. Am I missing something?

  31. Anonymous says:

    Why do I have to read/write unreadable xml? XML should not be written or read by humans. Please, can I get something more readable like JavaDoc style?

  32. Anonymous says:

    Suggestion: mention the syntax <typeparam name="T"> in the section, "How do use XML doc comments to refer to generic types?", or, add a new nearby section that describes typeparam.  It’s necessary to know the typeparam syntax in order to document generic types, and the syntax is not obvious a priori.