Understanding C#: XML Comments

By Andrew Stellman
June 14, 2010

I'm always looking for ways to help beginning and intermediate C# developers improve their skills and broaden their knowledge, because it can be just a little overwhelming for them. There's so much depth in the world of C# and .NET, so it can be hard to get started. When Jennifer Greene and I were working on Head First C#, we had to make a lot of tough choices about what to include in the book, and how we introduced it all -- since we're focused on really getting concepts into your brain as efficiently as possible, we have to choose which concepts to attack.

As C# developers get more experienced, there are a lot of things they pick up along the way that are really useful and important to know, even if they aren't necessarily directly code-related. One of those topics is XML comments, and I've been surprised at how many developers -- even really experienced ones -- don't use them, or even know about them. They're really useful, and they can help you build better software, even if they don't actually change the way your programs behave.

Head First C# Cover

We all know that we should comment our code, but the plain truth is that a lot of developers don't do such a good job with it. And while really well-written code should be easy to read, there's definitely value in comments. That's why XML comments are nice: the Visual Studio IDE gives you an instant reward for using them, in the form of better IntelliSense for your classes.

So for this post, I'm going to give you a really quick starting point for using XML comments.

Adding XML comments to a class

We're going to start building a class called Guy -- it's a very small, simple class that I like to use whenever I need an example of a class that keeps track of its state. I've found that it makes for a really good learning tool to get a handle on how XML comments work.

Before you get started, take a look at the source for the Guy class below. Notice how the class, its methods, and its properties are all commented with triple-slash (///) comments? Those are the XML comments, and the IDE will help you add them. Just type "///" right before a class, method, property, or field declaration (it works a few other places, too!), and the IDE will fill in the skeleton of the XML comment for it. Then later, when you go to use the property, method, etc., the IDE will display information from the XML comments alongside its IntelliSense window.

As usual, the easiest way to get a handle on this is to do it yourself, so let's get started by creating a new Console Application project in Visual Studio. Then add a class file called Guy.cs (Alt-Shift-C). Go right above the class declaration (class Guy) and enter three slashes: ///. The IDE should automatically fill in this snippet:

/// <summary>
///
/// </summary>

That's the skeleton for an XML comment. The XML comment for a class consists of one

block. Notice how it starts with and ends with . When the IDE adds the skeleton for a constructor or another method, it adds tags for each of the parameters.

Go ahead and fill in the rest of the XML comment for the Guy class:

/// <summary>
/// A guy with a name, age and a wallet full of bucks
/// </summary>

Here's the whole Guy class. If you want to get a sense of how XML comments are integrated into the IDE, it's actually worth typing some of them in, rather than copying and pasting. When you add the XML comment for a method, the IDE will automatically add a <param> tag for each parameter, and a <returns> tag if it has a return value.

Guy.cs
/// <summary>
/// A guy with a name, age and a wallet full of bucks
/// </summary>
class Guy
{
     /// <summary>
     /// Read-only backing field for the Name property
     /// </summary>
     private readonly string name;
 
     /// <summary>
     /// The name of the guy
     /// </summary>
     public string Name { get { return name; } }
 
     /// <summary>
     /// Read-only backing field for the Name property
     /// </summary>
     private readonly int age;
 
     /// <summary>
     /// The guy's age
     /// </summary>
     public int Age { get { return age; } }
 
     /// <summary>
     /// The number of bucks the guy has
     /// </summary>
     public int Cash { get; private set; }
 
     /// <summary>
     /// The constructor sets the name, age and cash
     /// </summary>
     /// <param name="name">The name of the guy</param>
     /// <param name="age">The guy's age</param>
     /// <param name="cash">The amount of cash the guy starts with</param>
     public Guy(string name, int age, int cash) {
          this.name = name;
          this.age = age;
          Cash = cash;
      }
 
     public override string ToString() {
          return String.Format("{0} is {1} years old and has {2} bucks", Name, Age, Cash);
      }
 
     /// <summary>
     /// Give cash from my wallet
     /// </summary>
     /// <param name="amount">The amount of cash to give</param>
     /// <returns>The amount of cash I gave, or 0 if I don't have enough cash</returns>
     public int GiveCash(int amount) {
          if (amount <= Cash && amount > 0)
          {
               Cash -= amount;
               return amount;
           }
          else
          {
               return 0;
           }
      }
 
     /// <summary>
     /// Receive some cash into my wallet
     /// </summary>
     /// <param name="amount">Amount to receive</param>
     /// <returns>The amount of cash received, or 0 if no cash was received</returns>
     public int ReceiveCash(int amount) {
          if (amount > 0)
          {
               if (amount > 0)
               {
                    Cash += amount;
                    return amount;
                }
               Console.WriteLine("{0} says: {1} isn't an amount I'll take", Name, amount);
           }
          return 0;
      }
}

(Did you notice how Name and Age are properties with backing fields that are marked readonly? That means those backing fields can only be set when the object is initialized (in their declarations or in the constructor). Marking a field readonly is a useful tool for encapsulation, because it means that field can never be changed once the object is instantiated. Also, notice how cash is not marked readonly. That's because it might change during the life of the Guy.)

The IDE displays XML comments automatically

Here's where XML comments can make your life a little easier. Here's a quick little program to add to your Program.cs:

Program.cs
class Program
{
     static void Main(string[] args)
     {
          Guy bob = new Guy("Bob", 37, 125);
          Console.WriteLine("Before: {0}", bob);
          bob.ReceiveCash(25);
          Console.WriteLine("After: {0}", bob);
      }
}

As you go to type in your code, keep an eye out for what the IDE pops up in the IntelliSense window. As soon as you type Guy, the IDE should display this IntelliSense window:

Screenshot - IDE Xml Comments 1.png

The IDE automatically displays the XML comment for the class along with its IntelliSense window. You've probably noticed that most of the built-in .NET classes have similar comments. Now you know where they come from!

Finish the first line. As soon as you type (, the IDE will show you the parameters for the constructor:

Screenshot - IDE Xml Comments 2.png

Notice how it displays the summary for the construtor and the current parameter. As you enter the parameters, the IDE will boldface the one you're currently entering and display its summary below the summary for the constructor.

Add the second line, and then start typing the third line. As soon as you type the dot, the familiar IntelliSense window will pop up showing you all of the Guy members you can use:

Screenshot - IDE Xml Comments 3.png

Now, when you highlight a member in the dropdown, the IDE also shows you the XML comments for it.

Finish the third line. As you do, you'll get the same IntelliSense window with XML comments that you did for the constructor:

Screenshot - IDE Xml Comments 4.png

Here's a tip: if you run your program, it'll quickly run, end, and then the console window will disappear. But if you run your program outside the debugger (Ctrl-F5), the IDE runs it and keeps the console window up by displaying a prompt that says, Press any key to continue . . .

Add an XML documentation file to your build

There's another thing you can do with XML comments. Choose "(Project Name) Properties..." from the Project menu and click on the Build tab on the left. Scroll down to the Output section, click the "XML documentation file" checkbox, and enter a filename in the box next to it.

Screenshot - IDE Xml Comments - Output window.png

Now rebuild your code. Go to the bin/Debug folder -- you should now find an XML file in it. Double-click on it to open it up. You'll see all of the XML documentation you added.

This is enormously useful, because you can use it to generate HTML documentation for your code. My favorite way to do this is to use Sandcastle and Sandcastle Help File Builder. (I'll cover this in a later post.)

Andrew Stellman is the author of Head First C# and other books from O'Reilly. You can read more from Andrew at Building Better Software.


You might also be interested in:

News Topics

Recommended for You

Got a Question?