Rock Your Code: XML Documentation Of Code For Microsoft .NET

Have you ever had issues trying to figure out what the code that you were tasked to work on is doing? Is there any documentation for it? Do you need questions answered, but the original developer isn’t working at the company anymore? Well, there is an easy answer for problems with .NET projects…XML documentation and code comments! These days, I’m beginning to think that documentation of code in Microsoft .NET is becoming a lost art. This is a negative trend that I will try to impact positively with this article. If you use good coding standards, most of the documentation I will talk about is simple to generate!

Rock Your Code: XML Documentation Of Code For Microsoft .NET

Most of us don’t like documenting code, but it is vitally important for the developers using the code now, and even more in the future. Recently I ran a poll on Twitter, and as you can see, over 45% of the respondents either don’t use XML documentation or don’t know what it is.

In the past when I talked about this at conferences and in my books, I used the .NET Framework as an example. Sadly, I can’t do that anymore, since even the teams at Microsoft are doing a poor job of this… so don’t feel bad if you aren’t doing it either. The information that I will show is from my book titled Rock Your Code: Coding Standards for Microsoft .NET. Please keep reading!

The purpose of XML documentation is to document the intent of a class and its fields, properties, methods, events, and code. The documentation for an assembly can be used by tools to create human-readable documentation, such as web pages, help files, and PDF files. There are multiple excellent reasons to use XML documentation.

  • The compiler combines the structure of the code with the text of the comments into a single XML document.
  • The compiler verifies that the comments match the API signatures for relevant tags.
  • Tools that process XML documentation files can define XML elements and attributes specific to those tools.
  • Visual Studio uses this documentation to provide the help text in IntelliSense.

If you follow good coding standards, then your code should be easy to understand (self-documenting), but there is more that also needs to be done.

Setting it Up

First, we must configure the project to export the XML file that Visual Studio will create. Go to the Properties of the project and navigate to the Build → Output tab. Make sure to check the checkbox and fill in the path and the name of the file. By default, Visual Studio does not make these settings for you.

Rock Your Code: XML Documentation Of Code For Microsoft .NET

One added benefit to configuring this is that the Visual Studio analyzers will produce an error if a type or member has not been documented. This file is what is used to create, using other tools, a website, help file, PDF, etc., for developers who will be coding against the assembly.

Section Tags

All types, methods, fields, events, delegates, etc. should be documented using XML tags. These tags will allow IntelliSense to provide useful details while using the types. Also, automatic documentation generation tooling relies on these tags. Section tags define the different sections within the documentation for the type.

Section Tags Description Location
<completionlist> ** I Cannot Find Any Documentation On This Tag. **  
<example>  Contains examples (code or text) related to a member or a type Type or member
<exception>  Lists the exceptions that a method or property can throw Method, Event, or Property
<include> Let's you refer to comments in another file that describe the types and members in your source code.  
<inheritdoc> Inherit XML comments from base classes, interfaces, and similar methods. This eliminates unwanted copying and pasting of duplicate XML comments and automatically keeps XML comments synchronized.
I’m not a big fan of this since the actual documentation cannot be viewed when looking at the code.
 
<list> Used to define the heading row of either a table or definition list. When defining a table, you only need to supply an entry for the term in the heading.  
<overloads>  Provides a summary for multiple overloads of a method The first method in an overload list
<para> The text of the paragraph.  
<param>  Describes the parameters of a method Method
<permission> Allows you to document the access of a member. The PermissionSet class lets you specify access to a member.  
<remarks>  Describes preconditions and other additional information. Type or member
<returns>  Describes the return value of a method. Method
<seealso>  Adds an entry to the See Also section Type or member
<summary>  Short description. Type or member
<typeparam> Used in the comment for a generic type or method declaration to describe a type parameter. Add a tag for each type parameter of the generic type or method.  
<typeparamref> Use this tag to enable consumers of the documentation file to format the word in some distinct way, for example in italics.  
<value>  Describes the type of data a property accepts and/or returns Property


Inline Tags

Inline tags can be used within section tags.

Inline Tags Description
<see> Creates a hyperlink to another member or type.
<paramref> Gives you a way to indicate that a word in the code comments, for example in a <summary> or <remarks> block refers to a parameter. The XML file can be processed to format this word in some distinct way, such as with a bold or italic font.


Markup Tags

Markup tags are used to apply special formatting to a part of a section.

Markup Tags Description
<code> Changes the indentation policy for code examples
<c> Changes the font to a fixed-wide font (often used with the <code> tag)
<para> Creates a new paragraph
<list> Creates a bulleted list, numbered list, or table.
<b> Bold typeface
<i> Italics typeface


File Headers

Each file should contain a header block. The header block should consist of the following which adheres to the format defined by StyleCop.

// ****************************************************************
// Assembly         : dotNetTips.Spargine.6.Extensions
// Author           : David McCarter
// Created          : 01-16-2022
//
// Last Modified By : David McCarter
// Last Modified On : 07-14-2022
// *******************************************************************
// <copyright file="ImmutableArrayExtensions.cs"
//     company="David McCarter - dotNetTips.com">
//     McCarter Consulting (David McCarter)
// </copyright>
// <summary>Extension methods for the ImmutableArray.</summary>

Regrettably, I don’t know of a way to automatically keep the “Last Modified By” and “Last Modified On” up to date, so make sure you change these values if you work on the file.

Types & Members

At a minimum, XML documentation should be written for all public and protected classes and members. This documentation should be kept up to date with the code when changes are made. XML documentation of classes and members should at a minimum include the <summary> tag. You should strive to use any tag that is appropriate for the type or member. More information makes the intent for types and members easier for other developers to understand. Remember, these comments are for developers, not the end user.

Types

Here is an example of how to properly document a type.

/// <summary>
/// Class HttpEventListener. This class cannot be inherited.
/// Implements the <see cref="EventListener" />
/// </summary>
/// <example>
/// <b>Output:</b> HTTP RequestStart: 
///                00000011-0000-0000-0000-00008ed19d59
///                https://dotnettips.com:443/ 
///                HTTP/1.1 POLICY: RequestVersionOrLower
/// <b>Output:</b> HTTP RequestStop: 
///                00000011-0000-0000-0000-00008ed19d59
/// </example>
/// <seealso cref="EventListener" />
public sealed class HttpEventListener : EventListener

Members

When I document the code I write, I comment all members. At a minimum, all public and protected members should be documented using the tags previously described. I will show and explain a few examples. All the following examples are from my Spargine open-source libraries.

/// <summary>
/// Logs default application information as key/ value pairs to
///   <see cref="ILogger"/>.
/// </summary>
/// <param name="logger">The ILogger.</param>
/// <exception cref="ArgumentNullException">Logger cannot be
///   null.</exception>
/// <example>
/// <b>Output:</b>
/// AppInfo:Company - Microsoft Corporation
/// AppInfo:Version - 16.8.0
/// AppInfo:Copyright - © Microsoft Corp. All rights reserved.
/// AppInfo:Product - dotNetTips.Spargine
/// AppInfo:FileVersion - 15.0.0
/// AppInfo:Title - dotNetTips.Spargine
/// </example>
public static void LogApplicationInformation(ILogger logger)

This example uses the <exception> tag to let the caller know what Exceptions are thrown from the method. This is very useful when coding try/catch blocks. It also uses the <example> tag to show the caller, in this case, an example of the result.

This should also be used to show how to properly use the method. Here is an example.

/// <summary>
/// Executes an async Task&lt;T&gt; method which has a T return
///   type synchronously.
/// </summary>
/// <typeparam name="T">Return Type</typeparam>
/// <param name="task">Task&lt;T&gt; method to execute</param>
/// <returns>T.</returns>
/// <example>
/// TaskHelper.RunSync(() =&gt; SomeType.FireWithReturnAsync("Test
///   Message"));
/// </example>
public static T RunSync<T>(this Func<Task<T>> task)

Code

XML comments are for comments within methods. If you follow proper coding standards, then most code should be self-documenting. If more documentation is needed, you can use // or ///. Here is an example.

protected SalesforceService Service {
    get {
        lock(_lock) {
            // Determine if service needs to log in
            if (this._service.ServiceStatus == ServiceStatus.LoggedOut) {
                this.InitService();
            }
        }
        return this._service;
    }
}

Again, code comments like this make it much easier for developers to fix bugs or add features in the future. The more information you give, the better their fixes and updates will be. This will dramatically speed up their work on the code, as well.

Indent comments at the same level of indentation as the code you are documenting. All comments should pass spell check. Misspelled comments indicate sloppy development. These comments will be removed when the assembly is compiled.

Example of the XML File

Below I've provided a partial example of what a XML documentation file looks like. This file is used to generate human-readable documentation. Before there were public tools to create documentation, I wrote code that would convert the XML file into a Word document. I supplied these documents to companies that hired me on a contract basis so that when I left, they would know how to use the assembly.

Rock Your Code: XML Documentation Of Code For Microsoft .NET

Generate Comments with GhostDoc

GhostDoc is a free Visual Studio extension for developers who need to generate XML comments from source code using customizable templates. GhostDoc also helps you maintain clean and up-to-date documentation, produce help documentation in multiple formats, and uses an intelligent source code spell checker in Visual Studio, and more.

I have been using GhostDoc from Submain.com for a long time to make it incredibly easy to document my classes. If you use proper naming standards, then GhostDoc will write most of the documentation for you! You might have to tweak it a bit, but over 90% will be done automatically by the program.

Key Features

Here are some of the key features of GhostDoc.

  • Automatic XML Comment Generation
  • Customizable XMAL Comment Templates
  • Documentation from the Build.
  • Visual Comment Editor.
  • Documentation in your preferred format
  • Smart Spell Check
  • Easy Code Documentation Maintenance
  • Custom Help Content
  • StyleCop Compliance

I use GhostDoc Enterprise. There is also a Pro version along with a FREE Community version. The spell checker in GhostDoc works well to ensure that comments are spelled correctly, but also that types, members, and parameters are spelled correctly too!

GhostDoc will also use the documentation from interfaces, if available. For example, this is the default documentation for the Dispose() method from the IDisposable interface.

/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed 
///   and unmanaged resources; <c>false</c> to release only
///   unmanaged resources.</param>
protected virtual void Dispose(bool disposing)

The feature I use the most with GhostDoc is “Document File.” This will generate a file header and XML documentation for all the classes and members in a file at one time. On top of that, it will update the “Last Modified On” date in the file header!

More Examples

Click here to see how I document my open-source libraries: https://bit.ly/SpargineGitHub. For more about GhostDoc, you can view my 256 Seconds With dotNetDave – My Workflow Before I Submit Code Changes video by going to https://bit.ly/CheckInWorkFlow.

Summary

I hope that this article will inspire you to write good XML documentation and code comments for your projects. Your fellow developers will find it easier to use the assemblies you write, and it will make it much easier to make changes in the future - and a lot less costly! This and much more are documented in my book Rock Your Code: Coding Standards for Microsoft.NET , which is available on Amazon.com.



McCarter Consulting
Software architecture, code & app performance, code quality, Microsoft .NET & mentoring. Available!