XML ドキュメント コメント

C# ソース ファイルには、それらのファイルで定義されている型の API ドキュメントを生成する構造化されたコメントを含めることができます。 C# コンパイラにより、コメントと API シグニチャを表す構造化データを含む XML ファイルが生成されます。 その XML 出力を他のツールで処理して、たとえば Web ページや PDF ファイルの形式で、人間が判読できるドキュメントを作成できます。

このプロセスには、コードに API ドキュメントを追加するためのさまざまな利点があります。

  • C# コンパイラによって C# コードの構造体がコメントのテキストと結合され、1 つの XML ドキュメントができます。
  • C# コンパイラによって、関連するタグの API シグニチャとコメントが一致することが確認されます。
  • XML ドキュメント ファイルを処理するツールで、これらのツールに固有の XML 要素と属性を定義できます。

Visual Studio などのツールには、ドキュメント コメントで使用される多くの一般的な XML 要素に対応した IntelliSense が用意されています。

この記事では、次のトピックについて説明します。

  • ドキュメント コメントと XML ファイルの生成
  • C# コンパイラと Visual Studio によって検証されるタグ
  • 生成される XML ファイルの形式

XML ドキュメント出力の作成

3 つのスラッシュで示される特別なコメント フィールドを記述して、コードのドキュメントを作成します。 コメント フィールドには、コメントの後に続くコード ブロックを記述する XML 要素が含まれます。 次に例を示します。

/// <summary>
///  This class performs an important function.
/// </summary>
public class MyClass {}

GenerateDocumentationFile または DocumentationFile オプションのいずれかを設定すると、コンパイラでソース コード内の XML タグを含むすべてのコメント フィールドが検索され、それらのコメントから XML ドキュメント ファイルが作成されます。 このオプションが有効になっている場合、プロジェクトに宣言されていて公開される、XML ドキュメント コメントのないメンバーに対して、CS1591 警告がコンパイラで生成されます。

XML のコメントの書式

XML ドキュメント コメントには、ドキュメント コメントの開始位置と終了位置を示す区切り記号を使用する必要があります。 XML ドキュメント タグで使用する区切り記号は次のとおりです。

  • /// 単一行の区切り記号: ドキュメントの例と C# プロジェクト テンプレートで、この書式を使用します。 区切り記号の後に空白がある場合、それは XML 出力に含まれません。

    注意

    Visual Studio のコード エディターで /// 区切り記号を入力すると、<summary> および </summary> タグが自動的に挿入され、これらのタグ内にカーソルが配置されます。 [オプション] ダイアログ ボックスで、この機能をオンまたはオフにできます。

  • /** */ 複数行の区切り記号: /** */ 区切り記号には、次の書式設定規則があります。
    • /** 区切り記号がある行で、行の残りの部分が空白の場合、その行はコメントとして処理されません。 /** 区切り記号の後にある最初の文字が空白の場合、その空白文字は無視され、行の残りの部分が処理されます。 それ以外の場合、/** 区切り記号の後にある行のテキスト全体が、コメントの一部として処理されます。

    • */ 区切り記号がある行で、*/ 区切り記号までの部分がすべて空白の場合、その行は無視されます。 それ以外の場合、その行の */ 区切り記号までのテキストが、コメントの一部として処理されます。

    • /** 区切り記号で始まる行の後に来る行については、コンパイラは各行の先頭で共通のパターンを検索します。 このパターンは、空白 (省略可能) + アスタリスク (*) + 空白 (省略可能) で構成されます。 /** 区切り記号で始まらない、または */ 区切り記号で終わらない各行の先頭で共通のパターンが見つかった場合、各行のそのパターンはコンパイラで無視されます。

    • 次のコメントでは、<summary> で始まる行だけがコメントの一部として処理されます。 次の 3 つのタグ形式は、いずれも同じコメントを生成します。

      /** <summary>text</summary> */
      
      /**
      <summary>text</summary>
      */
      
      /**
      * <summary>text</summary>
      */
      
    • コンパイラは、2 行目と 3 行目の先頭で共通のパターン " * " を識別します。 このパターンは出力に含まれません。

      /**
      * <summary>
      * text </summary>*/
      
    • 次のコメントでは、3 行目の 2 番目の文字がアスタリスクではないため、コンパイラで共通のパターンは検出されません。 2 行目と 3 行目のすべてのテキストがコメントの一部として処理されます。

      /**
      * <summary>
         text </summary>
      */
      
    • 次のコメントでは、2 つの原因によりコンパイラはパターンを検出しません。 まず、アスタリスクの前の空白の数が一致していません。 次に、5 行目がタブで始まっていて、空白と一致しません。 2 行目から 5 行目のすべてのテキストがコメントの一部として処理されます。

      /**
        * <summary>
        * text
      *  text2
       	*  </summary>
      */
      

XML 要素を参照するには (たとえば、XML ドキュメント コメントに記述する特定の XML 要素を関数で処理する場合)、標準の引用のしくみを使用できます (&lt;&gt;)。 コード参照 (cref) 要素でジェネリック識別子を参照するには、エスケープ文字 (たとえば、cref="List&lt;T&gt;") または中かっこ (cref="List{T}") を使用できます。 特殊なケースとして、コンパイラは中かっこを山かっことして解析し、ジェネリック識別子を参照するときにドキュメント コメントの編集があまり面倒にならないようにしています。

注意

XML ドキュメント コメントはメタデータではなく、コンパイルされたアセンブリに含まれないため、リフレクションでアクセスできません。

XML ドキュメント入力が受け入れられるツール

次のツールを使用すると、XML コメントから出力が作成されます。

  • DocFX: DocFX は .NET 用の API ドキュメント ジェネレーターであり、C#、Visual Basic、F# が現在サポートされています。 また、生成されたリファレンス ドキュメントをカスタマイズすることもできます。 DocFX でソース コードと Markdown ファイルから静的な HTML Web サイトを構築できます。 また、DocFX でテンプレートを使用して、Web サイトのレイアウトとスタイルを柔軟にカスタマイズできます。 また、カスタム テンプレートを作成することもできます。
  • Sandcastle: Sandcastle ツールにより、概念と API リファレンスの両方のページを含むマネージド クラス ライブラリのヘルプ ファイルを作成できます。 Sandcastle ツールはコマンド ライン ベースであり、GUI フロントエンド、プロジェクト管理機能、または自動ビルド プロセスはありません。 Sandcastle Help File Builder には、スタンドアロンの GUI およびコマンド ライン ベースのツールが用意されており、自動的にヘルプ ファイルを作成できます。 また、Visual Studio 統合パッケージを使用して、完全に Visual Studio 内からヘルプ プロジェクトを作成および管理できるようにすることもできます。
  • Doxygen: Doxygen により、ドキュメント化されたソース ファイルのセットからオンライン ドキュメント ブラウザー (HTML 形式) またはオフラインのリファレンス マニュアル (LaTeX) が生成されます。 また、RTF (MS Word)、PostScript、ハイパーリンク PDF、圧縮 HTML、DocBook、Unix man ページでの出力の生成もサポートされています。 ドキュメント化されていないソース ファイルからコード構造を抽出するように Doxygen を構成できます。

ID 文字列

各型またはメンバーは、出力 XML ファイルの要素に格納されます。 これらの各要素には、型またはメンバーを識別する一意の ID 文字列があります。 ID 文字列は、演算子、パラメーター、戻り値、ジェネリック型パラメーター、refin、および out パラメーターを考慮したものである必要があります。 これらの潜在的なすべての要素をエンコードするために、コンパイラには、ID 文字列の生成に関して明確に定義された規則が適用されます。 XML ファイルを処理するプログラムの場合、ID 文字列を使用して、対応する .NET のメタデータまたはドキュメントを適用するリフレクション項目を識別します。

コンパイラは、次の規則に基づいて ID 文字列を生成します。

  • 文字列に空白文字は含まれません。

  • この文字列の最初の部分は、単一の文字とそれに続くコロンで識別されるメンバーの種類を示します。 使用されるメンバー型は次のとおりです。

    文字 メンバーの型 メモ
    N namespace ドキュメント コメントを名前空間に追加することはできませんが、名前空間への cref 参照を行うことはできます (サポートされている場合)。
    T クラス、インターフェイス、構造体、列挙型、またはデリゲートの型です。
    F フィールド
    P property インデクサーまたはその他のインデックス付きプロパティが含まれます。
    M メソッド コンストラクターや演算子などの特殊なメソッドが含まれます。
    E イベント
    ! エラー文字列 あとに続く文字列で、エラーの情報を示します。 C# コンパイラは、解決できないリンクのエラー情報を生成します。
  • 文字列の 2 番目の部分は、項目の完全修飾名で、名前空間のルートから始まります。 項目の名前、それを囲む型、名前空間は、ピリオドで区切られます。 項目の名前自体にピリオドが含まれる場合、それはハッシュ記号 ('#') に置き換えられます。 項目の名前には、ハッシュ記号がないことが前提です。 たとえば、String コンストラクターの完全修飾名は "System.String.#ctor" です。

  • プロパティおよびメソッドについては、パラメーターのリストをかっこで囲み、プロパティとメソッドに続けて指定します。 パラメーターがない場合、かっこはありません。 パラメーターはコンマで区切ります。 各パラメーターのエンコードは、.NET シグネチャでのエンコード方法に直接従います (次の一覧にある全大文字の要素の定義については、「Microsoft.VisualStudio.CorDebugInterop.CorElementType」を参照してください)。

    • 基本データ型。 通常の型 (ELEMENT_TYPE_CLASS または ELEMENT_TYPE_VALUETYPE) は、型の完全修飾名として表されます。
    • 組み込み型 (たとえば、ELEMENT_TYPE_I4ELEMENT_TYPE_OBJECTELEMENT_TYPE_STRINGELEMENT_TYPE_TYPEDBYREFELEMENT_TYPE_VOID) は、対応する完全な型の完全修飾名として表されます。 たとえば、System.Int32 または System.TypedReference です。
    • ELEMENT_TYPE_PTR は、修飾される型に続けて '*' と表されます。
    • ELEMENT_TYPE_BYREF は、修飾される型に続けて '@' と表されます。
    • ELEMENT_TYPE_CMOD_OPT は、修飾される型に続けて "!" と修飾子クラスの完全修飾名で表されます。
    • ELEMENT_TYPE_SZARRAY は、配列の要素型に続けて "[]" と表されます。
    • ELEMENT_TYPE_ARRAY は、[ELEMENT_TYPE_ARRAY:size,size:size] の形式で表されます。ここで、コンマの個数はランク -1 個であり、各次元の下限とサイズは明らかな場合は、10 進数で表されます。 下限またはサイズの指定がない場合は省略されます。 特定の次元で下限およびサイズが省略されている場合は、':' も省略されます。 たとえば、ある 2 次元配列の下限が 1 で、サイズの指定がない場合は、[1:,1:] と表されます。
  • 変換演算子 (op_Implicit および op_Explicit) の場合のみ、メソッドの戻り値が ~ としてエンコードされ、それに続けて戻り値の型が表されます。 たとえば、<member name="M:System.Decimal.op_Explicit(System.Decimal arg)~System.Int32"> は、System.Decimal クラスで宣言された cast 演算子 public static explicit operator int (decimal value); のタグです。

  • ジェネリック型では、型の名前の後に、バックチック、ジェネリック型パラメーターの数を示す数値が順に続きます。 たとえば、<member name="T:SampleClass``2"> は、public class SampleClass<T, U> として定義されている型のタグです。 パラメーターとしてジェネリック型を受け取るメソッドでは、ジェネリック型パラメーターは、バックチック付きの数値 (`0、`1 など) として指定されます。 各数値は、型のジェネリック パラメーターに対する、0 から始まる配列表記を表しています。

    • ELEMENT_TYPE_PINNED は、修飾される型に続けて '^' と表されます。 このエンコードは C# コンパイラでは生成されません。
    • ELEMENT_TYPE_CMOD_REQ は、修飾される型に続けて '|' と修飾子クラスの完全修飾名で表されます。 このエンコードは C# コンパイラでは生成されません。
    • ELEMENT_TYPE_GENERICARRAY は、配列の要素型に続けて "[?]" と表されます。 このエンコードは C# コンパイラでは生成されません。
    • ELEMENT_TYPE_FNPTR は、"=FUNC:type(ELEMENT_TYPE_FNPTR)" と表されます。ここで、type は戻り値の型であり、type はメソッドの引数です。 引数がない場合、かっこは省略されます。 このエンコードは C# コンパイラでは生成されません。
    • 次に示すシグネチャ コンポーネントは、オーバーロードされるメソッドの区別には使用されないため、表されません。
      • 呼び出し規則
      • 戻り値の型
      • ELEMENT_TYPE_SENTINEL

次の例は、クラスおよびそのメンバーの ID 文字列を生成する方法を示します。

namespace MyNamespace
{
    /// <summary>
    /// Enter description here for class X.
    /// ID string generated is "T:MyNamespace.MyClass".
    /// </summary>
    public unsafe class MyClass
    {
        /// <summary>
        /// Enter description here for the first constructor.
        /// ID string generated is "M:MyNamespace.MyClass.#ctor".
        /// </summary>
        public MyClass() { }

        /// <summary>
        /// Enter description here for the second constructor.
        /// ID string generated is "M:MyNamespace.MyClass.#ctor(System.Int32)".
        /// </summary>
        /// <param name="i">Describe parameter.</param>
        public MyClass(int i) { }

        /// <summary>
        /// Enter description here for field message.
        /// ID string generated is "F:MyNamespace.MyClass.message".
        /// </summary>
        public string? message;

        /// <summary>
        /// Enter description for constant PI.
        /// ID string generated is "F:MyNamespace.MyClass.PI".
        /// </summary>
        public const double PI = 3.14;

        /// <summary>
        /// Enter description for method func.
        /// ID string generated is "M:MyNamespace.MyClass.func".
        /// </summary>
        /// <returns>Describe return value.</returns>
        public int func() { return 1; }

        /// <summary>
        /// Enter description for method someMethod.
        /// ID string generated is "M:MyNamespace.MyClass.someMethod(System.String,System.Int32@,System.Void*)".
        /// </summary>
        /// <param name="str">Describe parameter.</param>
        /// <param name="num">Describe parameter.</param>
        /// <param name="ptr">Describe parameter.</param>
        /// <returns>Describe return value.</returns>
        public int someMethod(string str, ref int nm, void* ptr) { return 1; }

        /// <summary>
        /// Enter description for method anotherMethod.
        /// ID string generated is "M:MyNamespace.MyClass.anotherMethod(System.Int16[],System.Int32[0:,0:])".
        /// </summary>
        /// <param name="array1">Describe parameter.</param>
        /// <param name="array">Describe parameter.</param>
        /// <returns>Describe return value.</returns>
        public int anotherMethod(short[] array1, int[,] array) { return 0; }

        /// <summary>
        /// Enter description for operator.
        /// ID string generated is "M:MyNamespace.MyClass.op_Addition(MyNamespace.MyClass,MyNamespace.MyClass)".
        /// </summary>
        /// <param name="first">Describe parameter.</param>
        /// <param name="second">Describe parameter.</param>
        /// <returns>Describe return value.</returns>
        public static MyClass operator +(MyClass first, MyClass second) { return first; }

        /// <summary>
        /// Enter description for property.
        /// ID string generated is "P:MyNamespace.MyClass.prop".
        /// </summary>
        public int prop { get { return 1; } set { } }

        /// <summary>
        /// Enter description for event.
        /// ID string generated is "E:MyNamespace.MyClass.OnHappened".
        /// </summary>
        public event Del? OnHappened;

        /// <summary>
        /// Enter description for index.
        /// ID string generated is "P:MyNamespace.MyClass.Item(System.String)".
        /// </summary>
        /// <param name="str">Describe parameter.</param>
        /// <returns></returns>
        public int this[string s] { get { return 1; } }

        /// <summary>
        /// Enter description for class Nested.
        /// ID string generated is "T:MyNamespace.MyClass.Nested".
        /// </summary>
        public class Nested { }

        /// <summary>
        /// Enter description for delegate.
        /// ID string generated is "T:MyNamespace.MyClass.Del".
        /// </summary>
        /// <param name="i">Describe parameter.</param>
        public delegate void Del(int i);

        /// <summary>
        /// Enter description for operator.
        /// ID string generated is "M:MyNamespace.MyClass.op_Explicit(MyNamespace.MyClass)~System.Int32".
        /// </summary>
        /// <param name="myParameter">Describe parameter.</param>
        /// <returns>Describe return value.</returns>
        public static explicit operator int(MyClass myParameter) { return 1; }
    }
}

C# 言語仕様

詳細については、ドキュメント コメントの C# 言語仕様の付属資料を参照してください。