C#ドキュメントコメントの書き方完全ガイド|XMLタグ一覧・サンプル・警告対策まで解説
はじめに
C#でライブラリや業務アプリケーションを開発していると、メソッドやクラスの上に /// で書かれたコメントを見かけることがあります。これが「C# ドキュメントコメント」です。
ドキュメントコメントは、単なるメモではありません。Visual StudioのIntelliSenseに表示されたり、XMLドキュメントファイルとして出力されたり、DocFXなどのツールでAPI仕様書に変換されたりします。特にチーム開発やライブラリ開発では、コードの使い方を正確に伝えるための重要な仕組みです。
この記事では、C#ドキュメントコメントの基本的な書き方から、よく使うXMLタグ、実践的なサンプル、XMLドキュメントファイルの生成方法、CS1591などの警告対策、読みやすいコメントを書くコツまでをまとめて解説します。
1. C#ドキュメントコメントとは
1-1. ドキュメントコメントの役割
C#ドキュメントコメントとは、クラス、メソッド、プロパティ、フィールド、イベントなどの型やメンバーに対して、使い方や仕様をXML形式で記述するコメントです。
代表的には次のように書きます。
C#/// <summary>
/// 指定された税込金額から税抜金額を計算します。
/// </summary>
/// <param name="amountWithTax">税込金額。</param>
/// <param name="taxRate">税率。10%の場合は0.10を指定します。</param>
/// <returns>税抜金額。</returns>
public decimal CalculateAmountWithoutTax(decimal amountWithTax, decimal taxRate)
{
return amountWithTax / (1 + taxRate);
}
このコメントは、開発者がソースコードを読むときだけでなく、メソッドを呼び出す側の補助情報としても利用されます。たとえば、Visual Studioでこのメソッドにカーソルを合わせると、summary や param の内容が表示されます。
1-2. 通常のコメントとの違い
C#には、通常のコメントとして // や /* */ があります。
C#// 合計金額を計算する
var total = price * quantity;
/*
複数行のコメント
*/
一方、ドキュメントコメントは /// を使って、対象の型やメンバーの直前に記述します。
C#/// <summary>
/// 合計金額を計算します。
/// </summary>
public decimal CalculateTotal(decimal price, int quantity)
{
return price * quantity;
}
通常のコメントは、主に実装の補足や注意点をソースコード内に残すためのものです。ドキュメントコメントは、外部から利用されるAPIの説明として扱われ、IntelliSenseやAPIドキュメント生成に利用できます。
つまり、通常のコメントは「実装を読む人のためのメモ」、ドキュメントコメントは「その型やメンバーを使う人のための説明」と考えるとわかりやすいです。
1-3. XMLドキュメントコメントが使われる場面
C#のドキュメントコメントはXML形式で記述されるため、「XMLドキュメントコメント」と呼ばれることもあります。
主な利用場面は次のとおりです。
C#/// <summary>
/// ユーザー情報を取得するサービスを表します。
/// </summary>
public interface IUserService
{
/// <summary>
/// 指定されたユーザーIDに対応するユーザーを取得します。
/// </summary>
/// <param name="userId">取得対象のユーザーID。</param>
/// <returns>ユーザー情報。</returns>
User GetUser(int userId);
}
このようなコメントは、アプリケーション内部の共通処理、社内ライブラリ、NuGetパッケージ、公開API、SDKなどで特に効果を発揮します。
利用者がソースコードの実装を読まなくても、「何をするメソッドなのか」「引数には何を渡すべきか」「戻り値は何か」「どのような例外が発生する可能性があるか」を把握できます。
1-4. IntelliSense・API仕様書・チーム開発でのメリット
C#ドキュメントコメントの大きなメリットは、コードの利用体験を改善できることです。
Visual StudioやRiderなどのIDEでは、ドキュメントコメントの内容が入力補完やツールチップに表示されます。これにより、開発者はメソッドの使い方をその場で確認できます。
また、XMLドキュメントファイルを生成すれば、DocFXやSandcastle Help File Builderなどのツールを使ってAPI仕様書を作成できます。ライブラリをNuGetパッケージとして配布する場合にも、XMLドキュメントを含めることで利用者の理解を助けられます。
チーム開発では、設計意図や利用上の注意を共有する手段として役立ちます。特に、ドメイン固有のルール、例外条件、nullの扱い、非同期処理の注意点などは、ドキュメントコメントに明記しておくと保守性が高まります。
2. C#ドキュメントコメントの基本的な書き方
2-1. ///で記述する基本構文
C#ドキュメントコメントは、対象となるクラスやメソッドの直前に /// を付けて記述します。
C#/// <summary>
/// ここに概要を書きます。
/// </summary>
public class SampleClass
{
}
基本的には、まず <summary> タグで概要を書きます。メソッドに引数がある場合は <param>、戻り値がある場合は <returns>、例外が発生する場合は <exception> を追加します。
C#/// <summary>
/// 指定された数値を2倍にします。
/// </summary>
/// <param name="value">2倍にする数値。</param>
/// <returns>指定された数値の2倍。</returns>
public int Double(int value)
{
return value * 2;
}
/// を使うと、Visual StudioではXMLタグの補完が働きます。メソッドの引数に応じて <param> タグが自動生成されるため、手作業で一から書く必要はありません。
2-2. クラスにコメントを書く例
クラスには、そのクラスが何を表すのか、どのような責務を持つのかを書きます。
C#/// <summary>
/// 商品情報を表します。
/// </summary>
public class Product
{
/// <summary>
/// 商品IDを取得または設定します。
/// </summary>
public int Id { get; set; }
/// <summary>
/// 商品名を取得または設定します。
/// </summary>
public string Name { get; set; } = string.Empty;
}
クラスのコメントでは、実装の細かい説明よりも「何を表す型なのか」を簡潔に書くことが大切です。
悪い例として、次のようなコメントは情報量が少なくなります。
C#/// <summary>
/// Productクラスです。
/// </summary>
public class Product
{
}
クラス名をそのまま繰り返すだけでは、利用者にとって役立つ情報になりません。次のように役割が伝わる内容にしましょう。
C#/// <summary>
/// 販売対象の商品情報を表します。
/// </summary>
public class Product
{
}
2-3. メソッドにコメントを書く例
メソッドには、「何をするか」「引数に何を渡すか」「何を返すか」を書きます。
C#/// <summary>
/// 指定された単価と数量から合計金額を計算します。
/// </summary>
/// <param name="unitPrice">商品の単価。</param>
/// <param name="quantity">購入数量。</param>
/// <returns>単価と数量を掛け合わせた合計金額。</returns>
public decimal CalculateTotal(decimal unitPrice, int quantity)
{
return unitPrice * quantity;
}
メソッドのコメントでは、内部でどのように計算しているかよりも、呼び出し側が知りたい情報を優先します。
たとえば、丸め処理、単位、null許可、例外条件などがある場合は、明確に書くと親切です。
C#/// <summary>
/// 指定された金額に消費税を加算します。
/// </summary>
/// <param name="amount">税抜金額。</param>
/// <param name="taxRate">税率。10%の場合は0.10を指定します。</param>
/// <returns>税込金額。小数点以下は四捨五入されません。</returns>
public decimal AddTax(decimal amount, decimal taxRate)
{
return amount * (1 + taxRate);
}
2-4. プロパティにコメントを書く例
プロパティには、その値が何を表すのかを書きます。
C#/// <summary>
/// ユーザー名を取得または設定します。
/// </summary>
public string UserName { get; set; } = string.Empty;
読み取り専用プロパティの場合は、「取得します」と書くと自然です。
C#/// <summary>
/// ユーザーが有効かどうかを示す値を取得します。
/// </summary>
public bool IsActive { get; }
プロパティの値について補足したい場合は <value> タグを使うこともできます。
C#/// <summary>
/// 注文ステータスを取得または設定します。
/// </summary>
/// <value>
/// 未処理、処理中、完了、キャンセル済みのいずれかを表します。
/// </value>
public OrderStatus Status { get; set; }
2-5. コンストラクター・イベント・フィールドに書く例
コンストラクターにもドキュメントコメントを書けます。どのような初期化を行うのか、引数に何を渡すのかを説明します。
C#/// <summary>
/// <see cref="UserService"/> クラスの新しいインスタンスを初期化します。
/// </summary>
/// <param name="repository">ユーザー情報の取得に使用するリポジトリ。</param>
public UserService(IUserRepository repository)
{
_repository = repository;
}
イベントには、どのタイミングで発生するのかを書きます。
C#/// <summary>
/// 注文が完了したときに発生します。
/// </summary>
public event EventHandler<OrderCompletedEventArgs>? OrderCompleted;
フィールドにもコメントは書けますが、公開フィールドは避け、必要に応じてプロパティを使う設計が一般的です。
C#/// <summary>
/// 既定のページサイズを表します。
/// </summary>
public const int DefaultPageSize = 20;
2-6. Visual Studioでコメントテンプレートを自動生成する方法
Visual Studioでは、クラスやメソッドの直前で /// と入力すると、ドキュメントコメントのテンプレートが自動生成されます。
たとえば、次のメソッドの上で /// を入力します。
C#public int Add(int x, int y)
{
return x + y;
}
すると、次のようなコメントが自動で作られます。
C#/// <summary>
///
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public int Add(int x, int y)
{
return x + y;
}
引数や戻り値に対応したタグを自動生成できるため、書き忘れを防ぎやすくなります。空欄のままにせず、利用者に伝わる説明を入れることが大切です。
3. よく使うXMLタグ一覧
3-1. <summary>:概要を書く
<summary> は、型やメンバーの概要を書く最も基本的なタグです。
C#/// <summary>
/// 指定されたユーザーIDに対応するユーザーを取得します。
/// </summary>
public User GetUser(int userId)
{
// ...
}
IntelliSenseで最も目立つ部分に表示されるため、短くわかりやすく書きます。
良い <summary> は、メンバー名を言い換えるだけではなく、振る舞いや目的を説明します。
C#/// <summary>
/// 有効なユーザーのみを検索対象として、指定されたメールアドレスに一致するユーザーを取得します。
/// </summary>
public User? FindActiveUserByEmail(string email)
{
// ...
}
3-2. <param>:引数を説明する
<param> は、メソッドやコンストラクターの引数を説明するタグです。
C#/// <summary>
/// 指定された範囲内の値かどうかを判定します。
/// </summary>
/// <param name="value">判定対象の値。</param>
/// <param name="min">許可される最小値。</param>
/// <param name="max">許可される最大値。</param>
/// <returns>値が範囲内の場合は true。それ以外の場合は false。</returns>
public bool IsInRange(int value, int min, int max)
{
return min <= value && value <= max;
}
name 属性には、実際の引数名を正確に指定します。引数名と一致しない場合、警告の原因になることがあります。
3-3. <returns>:戻り値を説明する
<returns> は、戻り値の意味を説明するタグです。
C#/// <summary>
/// 指定された文字列が数値に変換できるかどうかを判定します。
/// </summary>
/// <param name="text">判定対象の文字列。</param>
/// <returns>数値に変換できる場合は true。それ以外の場合は false。</returns>
public bool CanConvertToNumber(string text)
{
return int.TryParse(text, out _);
}
戻り値が bool の場合は、trueとfalseがそれぞれ何を意味するのかを書くとわかりやすくなります。
3-4. <remarks>:補足説明を書く
<remarks> は、概要だけでは伝えきれない補足説明を書くためのタグです。
C#/// <summary>
/// 注文を確定します。
/// </summary>
/// <remarks>
/// このメソッドは在庫数を減算し、注文ステータスを確定済みに変更します。
/// 決済処理は別途実行する必要があります。
/// </remarks>
public void ConfirmOrder()
{
// ...
}
<summary> には短い概要を書き、詳細な仕様や注意点は <remarks> に分けると読みやすくなります。
3-5. <value>:プロパティ値を説明する
<value> は、プロパティが保持する値の意味を説明するタグです。
C#/// <summary>
/// ユーザーの年齢を取得または設定します。
/// </summary>
/// <value>
/// 0以上の整数を指定します。
/// </value>
public int Age { get; set; }
単純なプロパティでは <summary> だけでも十分ですが、値の範囲や形式に制約がある場合は <value> を使うと便利です。
3-6. <exception>:発生する例外を説明する
<exception> は、メソッドが投げる可能性のある例外を説明するタグです。
C#/// <summary>
/// 指定されたIDのユーザーを取得します。
/// </summary>
/// <param name="userId">取得対象のユーザーID。</param>
/// <returns>ユーザー情報。</returns>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="userId"/> が0以下の場合にスローされます。
/// </exception>
/// <exception cref="UserNotFoundException">
/// 指定されたユーザーが存在しない場合にスローされます。
/// </exception>
public User GetUser(int userId)
{
if (userId <= 0)
{
throw new ArgumentOutOfRangeException(nameof(userId));
}
// ...
}
利用者が例外処理を考えやすくなるため、公開APIでは特に重要です。
3-7. <example>:使用例を書く
<example> は、使用例を書くためのタグです。
C#/// <summary>
/// 文字列を指定された区切り文字で分割します。
/// </summary>
/// <param name="text">分割対象の文字列。</param>
/// <param name="separator">区切り文字。</param>
/// <returns>分割された文字列の配列。</returns>
/// <example>
/// <code>
/// var result = SplitText("A,B,C", ',');
/// // result: ["A", "B", "C"]
/// </code>
/// </example>
public string[] SplitText(string text, char separator)
{
return text.Split(separator);
}
使用例があると、利用者はメソッドの使い方をすぐに理解できます。複雑なAPIやライブラリでは特に効果的です。
3-8. <code>・<c>:コードを記述する
<code> は複数行のコードを記述するタグです。
C#/// <example>
/// <code>
/// var calculator = new TaxCalculator();
/// var result = calculator.AddTax(1000, 0.10m);
/// </code>
/// </example>
一方、<c> は文中に短いコード片を書くときに使います。
C#/// <summary>
/// <c>null</c> または空文字列の場合に既定値を返します。
/// </summary>
public string GetValueOrDefault(string? value)
{
return string.IsNullOrEmpty(value) ? "default" : value;
}
長いコードは <code>、文中の短い識別子や値は <c> と使い分けます。
3-9. <see>・<seealso>:関連クラスやメンバーへリンクする
<see> は、関連する型やメンバーを文中で参照するタグです。
C#/// <summary>
/// <see cref="Order"/> を確定します。
/// </summary>
public void Confirm(Order order)
{
// ...
}
<seealso> は、関連項目として別の型やメンバーを示すときに使います。
C#/// <summary>
/// 注文をキャンセルします。
/// </summary>
/// <seealso cref="Confirm(Order)"/>
public void Cancel(Order order)
{
// ...
}
cref 属性には型名やメンバー名を指定します。名前が存在しない場合や解決できない場合、警告が出ることがあります。
3-10. <typeparam>・<typeparamref>:ジェネリック型を説明する
<typeparam> は、ジェネリック型パラメーターを説明するタグです。
C#/// <summary>
/// 値をキャッシュする簡易的なコンテナーを表します。
/// </summary>
/// <typeparam name="T">キャッシュする値の型。</typeparam>
public class Cache<T>
{
private T? _value;
}
<typeparamref> は、文中で型パラメーター名を参照するときに使います。
C#/// <summary>
/// <typeparamref name="T"/> 型の値を保存します。
/// </summary>
/// <typeparam name="T">保存する値の型。</typeparam>
public void Save<T>(T value)
{
// ...
}
ジェネリッククラスやジェネリックメソッドでは、型パラメーターの意味を明確にしておくと利用しやすくなります。
3-11. <paramref>:引数名を本文中で参照する
<paramref> は、コメント本文中で引数名を参照するときに使います。
C#/// <summary>
/// <paramref name="source"/> が <c>null</c> の場合は空の配列を返します。
/// </summary>
/// <param name="source">変換対象の配列。</param>
/// <returns>変換後の配列。</returns>
public string[] Normalize(string[]? source)
{
return source ?? Array.Empty<string>();
}
単に引数名を文字列として書くよりも、ドキュメントツールやIDEが引数として認識しやすくなります。
3-12. <list>:箇条書きを作る
<list> は、箇条書きや番号付きリストを書くためのタグです。
C#/// <summary>
/// パスワードがルールを満たしているか検証します。
/// </summary>
/// <remarks>
/// パスワードは次の条件を満たす必要があります。
/// <list type="bullet">
/// <item><description>8文字以上であること。</description></item>
/// <item><description>英字を含むこと。</description></item>
/// <item><description>数字を含むこと。</description></item>
/// </list>
/// </remarks>
public bool ValidatePassword(string password)
{
// ...
}
複数の条件や仕様を説明するときは、文章で長く書くよりもリストにした方が読みやすくなります。
3-13. <para>:段落を分ける
<para> は、説明文の段落を分けるために使います。
C#/// <summary>
/// レポートを生成します。
/// </summary>
/// <remarks>
/// <para>
/// このメソッドは売上データを集計し、月次レポートを生成します。
/// </para>
/// <para>
/// 大量のデータを扱う場合、処理に時間がかかることがあります。
/// </para>
/// </remarks>
public void GenerateReport()
{
// ...
}
<remarks> が長くなる場合は、<para> で段落を分けると読みやすくなります。
3-14. <inheritdoc>:コメントを継承する
<inheritdoc> は、基底クラスやインターフェースのドキュメントコメントを継承したいときに使われます。
C#public interface IUserRepository
{
/// <summary>
/// 指定されたIDのユーザーを取得します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザー情報。存在しない場合は null。</returns>
User? FindById(int id);
}
public class UserRepository : IUserRepository
{
/// <inheritdoc/>
public User? FindById(int id)
{
// ...
}
}
インターフェースにしっかりコメントを書き、実装クラスでは <inheritdoc/> を使うと、重複を減らせます。ただし、すべてのドキュメント生成ツールが同じように解釈するとは限らないため、使用するIDEやツールで表示を確認しておくと安心です。
3-15. <include>:外部XMLファイルを読み込む
<include> は、外部XMLファイルに記述したコメントを読み込むためのタグです。
C#/// <include file='Docs.xml' path='docs/members/member[@name="UserService"]/*'/>
public class UserService
{
}
コメントをソースコードから分離したい場合や、大量のドキュメントを外部管理したい場合に使えます。
ただし、通常のアプリケーション開発では、まずソースコード内に /// で直接書く方法から始めるのが一般的です。<include> は、ドキュメント量が多いライブラリや特殊な管理ルールがある場合に検討するとよいでしょう。
4. 実践サンプルで学ぶドキュメントコメント
4-1. 基本的なメソッドのコメント例
まずは、引数も戻り値もないシンプルなメソッドの例です。
C#/// <summary>
/// キャッシュされているデータをすべて削除します。
/// </summary>
public void ClearCache()
{
// キャッシュ削除処理
}
この場合、<summary> だけで十分です。メソッド名が ClearCache なので「キャッシュを削除します」と書くだけでも伝わりますが、「すべて削除する」のように範囲を補足するとより明確になります。
4-2. 引数と戻り値があるメソッドのコメント例
引数と戻り値がある場合は、<param> と <returns> を追加します。
C#/// <summary>
/// 指定された商品の税込価格を計算します。
/// </summary>
/// <param name="price">税抜価格。</param>
/// <param name="taxRate">税率。10%の場合は0.10を指定します。</param>
/// <returns>税込価格。</returns>
public decimal CalculatePriceWithTax(decimal price, decimal taxRate)
{
return price * (1 + taxRate);
}
ここでは、taxRate に 10 ではなく 0.10 を指定することを明記しています。このような入力形式は、実装を読まないと誤解されやすいため、ドキュメントコメントに書く価値があります。
4-3. 例外を投げるメソッドのコメント例
例外が発生する条件は、利用者が事前に知っておきたい重要な情報です。
C#/// <summary>
/// 指定された文字列を日付に変換します。
/// </summary>
/// <param name="text">変換対象の日付文字列。</param>
/// <returns>変換された日付。</returns>
/// <exception cref="ArgumentException">
/// <paramref name="text"/> が null、空文字列、または日付として解析できない場合にスローされます。
/// </exception>
public DateTime ParseDate(string? text)
{
if (string.IsNullOrWhiteSpace(text))
{
throw new ArgumentException("日付文字列を指定してください。", nameof(text));
}
if (!DateTime.TryParse(text, out var result))
{
throw new ArgumentException("日付として解析できません。", nameof(text));
}
return result;
}
<exception> には、どの例外がどの条件で発生するかを書きます。例外の型だけでなく、発生条件も説明すると実用的です。
4-4. ジェネリッククラス・ジェネリックメソッドのコメント例
ジェネリック型では、<typeparam> を使って型パラメーターを説明します。
C#/// <summary>
/// 値の取得結果を表します。
/// </summary>
/// <typeparam name="T">取得される値の型。</typeparam>
public class Result<T>
{
/// <summary>
/// 処理が成功したかどうかを示す値を取得します。
/// </summary>
public bool IsSuccess { get; init; }
/// <summary>
/// 取得された値を取得します。
/// </summary>
public T? Value { get; init; }
/// <summary>
/// エラーメッセージを取得します。
/// </summary>
public string? ErrorMessage { get; init; }
}
ジェネリックメソッドの場合も同様です。
C#/// <summary>
/// 指定された値が null の場合に例外をスローします。
/// </summary>
/// <typeparam name="T">検証する値の型。</typeparam>
/// <param name="value">検証対象の値。</param>
/// <param name="paramName">引数名。</param>
/// <returns>null ではない <paramref name="value"/>。</returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="value"/> が null の場合にスローされます。
/// </exception>
public T ThrowIfNull<T>(T? value, string paramName)
{
return value ?? throw new ArgumentNullException(paramName);
}
4-5. 非同期メソッドのコメント例
非同期メソッドでは、戻り値が Task や Task<T> になるため、<returns> には非同期処理の結果を書くとわかりやすくなります。
C#/// <summary>
/// 指定されたIDのユーザーを非同期で取得します。
/// </summary>
/// <param name="userId">取得対象のユーザーID。</param>
/// <returns>
/// ユーザー情報を表す <see cref="User"/> を結果として返すタスク。
/// ユーザーが存在しない場合は null を返します。
/// </returns>
public async Task<User?> GetUserAsync(int userId)
{
// 非同期処理
await Task.Delay(100);
return null;
}
Task<User> を返す場合でも、「Taskを返します」だけでは不十分です。呼び出し側が知りたいのは、非同期処理の結果として何が得られるかです。
4-6. インターフェースと実装クラスのコメント例
インターフェースには、利用者向けの仕様をしっかり書きます。
C#/// <summary>
/// ユーザー情報を永続化するリポジトリを表します。
/// </summary>
public interface IUserRepository
{
/// <summary>
/// 指定されたIDのユーザーを取得します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザーが存在する場合はユーザー情報。それ以外の場合は null。</returns>
User? FindById(int id);
}
実装クラスでは、同じ内容を繰り返したくない場合に <inheritdoc/> を使えます。
C#/// <summary>
/// データベースを使用してユーザー情報を永続化するリポジトリです。
/// </summary>
public class DatabaseUserRepository : IUserRepository
{
/// <inheritdoc/>
public User? FindById(int id)
{
// データベース検索処理
return null;
}
}
実装固有の注意点がある場合は、<inheritdoc/> に加えて補足を書くことも検討します。
4-7. enumのコメント例
enum には、列挙型そのものと各値の意味を書きます。
C#/// <summary>
/// 注文の状態を表します。
/// </summary>
public enum OrderStatus
{
/// <summary>
/// 注文が作成された直後の状態です。
/// </summary>
Pending,
/// <summary>
/// 注文処理が進行中の状態です。
/// </summary>
Processing,
/// <summary>
/// 注文が完了した状態です。
/// </summary>
Completed,
/// <summary>
/// 注文がキャンセルされた状態です。
/// </summary>
Canceled
}
enum の各値は、画面表示、分岐処理、外部連携などで利用されることが多いため、意味を明確にしておくと保守しやすくなります。
4-8. XMLタグを組み合わせた実用的なコメント例
実務では、複数のXMLタグを組み合わせて使うことが多くなります。
C#/// <summary>
/// 指定された条件に一致する注文を検索します。
/// </summary>
/// <remarks>
/// <para>
/// 検索対象は確定済みの注文のみです。
/// </para>
/// <para>
/// 検索条件を指定しない場合、すべての確定済み注文を返します。
/// </para>
/// </remarks>
/// <param name="customerId">顧客ID。指定しない場合はすべての顧客を対象にします。</param>
/// <param name="from">検索開始日。指定しない場合は開始日で絞り込みません。</param>
/// <param name="to">検索終了日。指定しない場合は終了日で絞り込みません。</param>
/// <returns>条件に一致する注文の一覧。</returns>
/// <exception cref="ArgumentException">
/// <paramref name="from"/> が <paramref name="to"/> より後の日付の場合にスローされます。
/// </exception>
/// <example>
/// <code>
/// var orders = orderService.SearchOrders(
/// customerId: 10,
/// from: new DateTime(2025, 1, 1),
/// to: new DateTime(2025, 1, 31));
/// </code>
/// </example>
/// <seealso cref="Order"/>
public IReadOnlyList<Order> SearchOrders(
int? customerId,
DateTime? from,
DateTime? to)
{
if (from.HasValue && to.HasValue && from > to)
{
throw new ArgumentException("検索開始日は検索終了日以前である必要があります。");
}
return Array.Empty<Order>();
}
このように、概要、補足、引数、戻り値、例外、使用例、関連型を整理して書くことで、利用者がAPIを迷わず使えるようになります。
5. XMLドキュメントファイルを出力する方法
5-1. Visual StudioでXMLドキュメントファイルを生成する
C#ドキュメントコメントは、XMLドキュメントファイルとして出力できます。
Visual Studioでは、プロジェクトのプロパティから設定できます。
プロジェクトを右クリックする
「プロパティ」を開く
「ビルド」または「出力」に関する設定を開く
「XMLドキュメントファイル」または「ドキュメントファイルを生成する」を有効にする
この設定を有効にすると、ビルド時にアセンブリと同名の .xml ファイルが生成されます。
たとえば、出力されるDLLが MyLibrary.dll の場合、MyLibrary.xml のようなファイルが作成されます。
5-2. .csprojでGenerateDocumentationFileを設定する
SDK形式のプロジェクトでは、.csproj に次のように設定できます。
XML<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
これにより、ビルド時にXMLドキュメントファイルが生成されます。
出力先を明示したい場合は、DocumentationFile を指定できます。
XML<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\MyLibrary.xml</DocumentationFile>
</PropertyGroup>
通常は GenerateDocumentationFile を有効にするだけで十分です。出力先を特別に制御したい場合のみ、DocumentationFile を設定します。
5-3. .NET CLIでビルド時に生成する
.csproj に GenerateDocumentationFile を設定していれば、.NET CLIでビルドしたときにもXMLドキュメントファイルが生成されます。
Bashdotnet build
リリースビルドで生成する場合は、次のように実行します。
Bashdotnet build -c Release
一時的にコマンドラインからプロパティを指定することもできます。
Bashdotnet build -p:GenerateDocumentationFile=true
CI/CDでNuGetパッケージを作成する場合は、.csproj に設定を入れておくと、ローカル環境とビルド環境で出力結果をそろえやすくなります。
5-4. 生成されたXMLファイルの中身
生成されたXMLドキュメントファイルには、コメントの内容がXML形式で出力されます。
たとえば、次のようなC#コードがあるとします。
C#/// <summary>
/// 計算処理を提供します。
/// </summary>
public class Calculator
{
/// <summary>
/// 2つの数値を加算します。
/// </summary>
/// <param name="x">1つ目の数値。</param>
/// <param name="y">2つ目の数値。</param>
/// <returns>加算結果。</returns>
public int Add(int x, int y)
{
return x + y;
}
}
XMLファイルには、次のような内容が出力されます。
XML<?xml version="1.0"?>
<doc>
<assembly>
<name>MyLibrary</name>
</assembly>
<members>
<member name="T:MyLibrary.Calculator">
<summary>
計算処理を提供します。
</summary>
</member>
<member name="M:MyLibrary.Calculator.Add(System.Int32,System.Int32)">
<summary>
2つの数値を加算します。
</summary>
<param name="x">1つ目の数値。</param>
<param name="y">2つ目の数値。</param>
<returns>加算結果。</returns>
</member>
</members>
</doc>
T: は型、M: はメソッド、P: はプロパティ、F: はフィールド、E: はイベントを表します。ドキュメント生成ツールは、このXMLを読み取ってAPI仕様書を作成します。
5-5. NuGetパッケージやライブラリ公開時に含める方法
ライブラリをNuGetパッケージとして公開する場合、XMLドキュメントファイルを含めると利用者のIDE上でコメントが表示されます。
SDK形式のプロジェクトでは、GenerateDocumentationFile を有効にして dotnet pack を実行することで、XMLドキュメントファイルがパッケージに含まれる構成にしやすくなります。
XML<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageId>MyLibrary</PackageId>
<Version>1.0.0</Version>
</PropertyGroup>
Bashdotnet pack -c Release
公開ライブラリでは、少なくともpublicなクラス、メソッド、プロパティにはドキュメントコメントを書くことをおすすめします。利用者がソースコードを読まなくても使い方を理解できる状態にしておくことが、ライブラリの品質向上につながります。
6. ドキュメントコメント関連の警告と対策
6-1. CS1591とは
CS1591は、XMLドキュメントファイルの生成を有効にしているときに、公開されている型やメンバーにドキュメントコメントがない場合に発生する警告です。
代表的なメッセージは次のような内容です。
CS1591: 公開されている型またはメンバー 'SampleClass.SampleMethod()' の XML コメントがありません
この警告は、publicなAPIに説明が不足していることを知らせるものです。ライブラリ開発では有用ですが、アプリケーション開発では大量に出て困る場合もあります。
6-2. 「公開されている型またはメンバーのXMLコメントがありません」の原因
CS1591が発生する主な原因は、次のようなpublicメンバーにコメントがないことです。
C#public class UserService
{
public User GetUser(int id)
{
// ...
}
}
XMLドキュメントファイルの生成が有効な状態で、このようなpublicクラスやpublicメソッドにドキュメントコメントがないと警告が出ます。
対象になりやすいものは次のとおりです。
C#public class SampleClass { }
public interface ISampleService { }
public enum SampleStatus { Active, Inactive }
public class Sample
{
public string Name { get; set; } = string.Empty;
public event EventHandler? Changed;
public void Execute() { }
}
publicな型、メソッド、プロパティ、イベント、フィールド、enumの値などが対象になります。
6-3. CS1591を修正する方法
最も基本的な対策は、対象の型やメンバーにドキュメントコメントを追加することです。
C#/// <summary>
/// ユーザー情報を操作するサービスです。
/// </summary>
public class UserService
{
/// <summary>
/// 指定されたIDのユーザーを取得します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザー情報。</returns>
public User GetUser(int id)
{
// ...
}
}
外部に公開する必要がないメンバーであれば、アクセス修飾子を internal や private に変更することも検討します。
C#internal class UserService
{
}
不要にpublicにしている型やメンバーを見直すことは、警告対策だけでなく設計の改善にもつながります。
6-4. CS1591を抑制する方法
プロジェクト全体でCS1591を抑制したい場合は、.csproj に NoWarn を設定します。
XML<PropertyGroup>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
または、特定の範囲だけ #pragma を使って抑制できます。
C##pragma warning disable CS1591
public class TemporaryClass
{
public void Execute()
{
}
}
#pragma warning restore CS1591
ただし、公開ライブラリでCS1591を無条件に抑制すると、APIドキュメントの品質が下がる可能性があります。抑制する前に、本当にコメントが不要かを確認しましょう。
6-5. 特定ファイルだけ警告を無効化する方法
特定のファイルだけCS1591を無効化したい場合は、そのファイルの先頭に #pragma warning disable を書きます。
C##pragma warning disable CS1591
namespace MyApp.Generated;
public class GeneratedModel
{
public string Name { get; set; } = string.Empty;
}
#pragma warning restore CS1591
ファイル全体を対象にしたい場合は、先頭で無効化し、末尾で復元する形にします。
一時的な対応としては便利ですが、手作業で多用すると警告の管理が複雑になります。生成コードや移行中のコードなど、対象を明確にしたうえで使うのがよいでしょう。
6-6. 自動生成コードで警告が出る場合の対処法
自動生成コードでCS1591が出る場合は、まず生成されたコードが本当にXMLドキュメントの対象になるべきかを確認します。
対処法としては、次のような方法があります。
C##pragma warning disable CS1591
// 自動生成されたコード
#pragma warning restore CS1591
また、生成ツール側でコメントを出力できる場合は、コメント生成を有効にするのも有効です。
ソースジェネレーターやテンプレートから生成されるコードでは、生成結果にpublicメンバーが含まれることがあります。その場合は、生成コードをinternalにできないか、ドキュメントコメントを生成できないか、警告を限定的に抑制できないかを検討します。
6-7. NoWarnで警告を管理する方法
NoWarn は、特定の警告番号をプロジェクト単位で抑制するために使います。
XML<PropertyGroup>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
複数の警告を抑制する場合は、セミコロンで区切ります。
XML<PropertyGroup>
<NoWarn>$(NoWarn);1591;1573;1572</NoWarn>
</PropertyGroup>
ただし、警告をまとめて抑制すると、重要な問題に気づきにくくなります。NoWarn は便利ですが、「なぜ抑制するのか」をチーム内で共有しておくことが大切です。
6-8. 警告をエラー扱いにするべきケース
公開ライブラリやSDKを開発している場合は、ドキュメントコメント関連の警告をエラー扱いにすることを検討できます。
XML<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
すべての警告をエラー扱いにするのが厳しい場合は、特定の警告だけを対象にします。
XML<PropertyGroup>
<WarningsAsErrors>1591</WarningsAsErrors>
</PropertyGroup>
公開APIの品質を保ちたい場合、CS1591をエラーにすることで、コメント漏れをビルド時に検出できます。
一方、社内アプリケーションや小規模プロジェクトでは、すべてのpublicメンバーにコメントを強制すると開発効率が落ちる場合もあります。プロジェクトの性質に応じて判断しましょう。
7. 読みやすいドキュメントコメントを書くコツ
7-1. 何を書くべきか・何を書かないべきか
ドキュメントコメントには、利用者がその型やメンバーを正しく使うために必要な情報を書きます。
書くべき内容は、主に次のようなものです。
・何をするメソッドか
・引数に何を渡すか
・戻り値が何を意味するか
・どのような条件で例外が発生するか
・nullを許可するか
・単位や形式に決まりがあるか
・呼び出し順序や副作用があるか
反対に、実装を読めばすぐにわかる内部処理や、将来変わる可能性が高い細部を書きすぎると、コメントと実装がずれやすくなります。
7-2. メソッド名を繰り返すだけのコメントを避ける
次のようなコメントは、情報量が少ないため避けたい例です。
C#/// <summary>
/// GetUserします。
/// </summary>
public User GetUser(int id)
{
// ...
}
メソッド名をそのまま日本語にしただけでは、利用者の疑問に答えられません。
改善するなら、次のように書きます。
C#/// <summary>
/// 指定されたIDに一致するユーザーを取得します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザー情報。</returns>
public User GetUser(int id)
{
// ...
}
さらに、見つからない場合の挙動も書くと実用的です。
C#/// <summary>
/// 指定されたIDに一致するユーザーを取得します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザーが存在する場合はユーザー情報。それ以外の場合は null。</returns>
public User? FindUser(int id)
{
// ...
}
7-3. 利用者目線で振る舞いを書く
ドキュメントコメントは、実装者ではなく利用者のために書きます。
悪い例です。
C#/// <summary>
/// LINQでWhereしてFirstOrDefaultします。
/// </summary>
public User? FindUser(string email)
{
// ...
}
これは内部実装の説明になっています。利用者にとって重要なのは、どのような条件で何が返るかです。
C#/// <summary>
/// 指定されたメールアドレスに一致する有効なユーザーを取得します。
/// </summary>
/// <param name="email">検索するメールアドレス。</param>
/// <returns>一致するユーザーが存在する場合はユーザー情報。それ以外の場合は null。</returns>
public User? FindUser(string email)
{
// ...
}
実装方法は変わる可能性がありますが、公開APIの振る舞いは利用者にとって重要な契約です。
7-4. 引数・戻り値・例外は具体的に書く
引数の説明では、単に「値」と書くだけでは不十分な場合があります。
C#/// <param name="rate">値。</param>
より具体的に書きます。
C#/// <param name="rate">税率。10%の場合は0.10を指定します。</param>
戻り値も同様です。
C#/// <returns>結果。</returns>
ではなく、次のように意味を書きます。
C#/// <returns>検証に成功した場合は true。それ以外の場合は false。</returns>
例外についても、「エラー時に発生します」ではなく、発生条件を明確にします。
C#/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="quantity"/> が0以下の場合にスローされます。
/// </exception>
7-5. コメントと実装の不一致を防ぐ
ドキュメントコメントで最も避けたいのは、実装とコメントが食い違うことです。
たとえば、コメントには「nullを返します」と書いてあるのに、実装では例外を投げる場合、利用者は誤った前提でコードを書いてしまいます。
C#/// <summary>
/// 指定されたIDのユーザーを取得します。
/// </summary>
/// <returns>ユーザーが存在しない場合は null。</returns>
public User GetUser(int id)
{
throw new UserNotFoundException();
}
この場合は、戻り値や例外の説明を実装に合わせる必要があります。
C#/// <summary>
/// 指定されたIDのユーザーを取得します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザー情報。</returns>
/// <exception cref="UserNotFoundException">
/// 指定されたIDのユーザーが存在しない場合にスローされます。
/// </exception>
public User GetUser(int id)
{
// ...
}
コメントもコードの一部として扱い、仕様変更時には必ず更新しましょう。
7-6. 日本語と英語の使い分け
日本語で開発しているチームでは、日本語のドキュメントコメントで問題ありません。
C#/// <summary>
/// 注文の合計金額を計算します。
/// </summary>
public decimal CalculateTotal()
{
// ...
}
一方、OSS、海外向けライブラリ、多国籍チームで使うコードでは、英語で書く方が適している場合があります。
C#/// <summary>
/// Calculates the total amount of the order.
/// </summary>
public decimal CalculateTotal()
{
// ...
}
重要なのは、プロジェクト内で言語を統一することです。同じコードベース内で日本語と英語が混在すると、読みづらくなる場合があります。
7-7. チーム開発でルール化すべきポイント
チーム開発では、ドキュメントコメントの書き方をルール化しておくと品質を保ちやすくなります。
たとえば、次のようなルールが考えられます。
・publicな型とメンバーには原則コメントを書く
・privateメンバーは必要な場合のみ書く
・summaryは1〜2文で簡潔に書く
・param、returns、exceptionは具体的に書く
・コメントと実装がずれた場合は実装変更時に必ず修正する
・日本語または英語のどちらを使うか統一する
・インターフェースにコメントを書き、実装ではinheritdocを活用する
ルールが厳しすぎると形だけのコメントが増えます。逆に緩すぎると重要なAPIの説明が不足します。プロジェクトの規模や公開範囲に合わせて、現実的なルールにすることが大切です。
8. ドキュメントコメントを効率化するツール
8-1. Visual Studioの入力補完を使う
Visual Studioでは、メンバーの直前で /// を入力すると、ドキュメントコメントのテンプレートが自動生成されます。
C#/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public string CreateMessage(string name)
{
return $"Hello, {name}";
}
引数が多いメソッドでも <param> が自動で作られるため、書き漏れを減らせます。
また、<see cref=""> の cref では型名やメンバー名の補完が使えるため、リンク切れを防ぎやすくなります。
8-2. Rider・ReSharperで不足コメントを検出する
RiderやReSharperを使うと、ドキュメントコメントの不足や不整合を検出しやすくなります。
たとえば、publicメンバーにコメントがない場合、引数の <param> が不足している場合、存在しない型を cref で参照している場合などをIDE上で確認できます。
ドキュメントコメントは、後からまとめて書くよりも、コードを書いたタイミングで整える方が楽です。IDEの警告や補完を活用して、日常的に修正する習慣をつけるとよいでしょう。
8-3. StyleCop Analyzersでルールを統一する
StyleCop Analyzersを導入すると、C#コードのスタイルやドキュメントコメントに関するルールを静的解析できます。
たとえば、公開メンバーにドキュメントコメントを要求したり、コメントの形式をチェックしたりできます。
.editorconfig と組み合わせることで、チーム全体で同じルールを適用できます。
INIdotnet_diagnostic.SA1600.severity = warning
ただし、すべてのルールを厳格に有効にすると、警告が多くなりすぎる場合があります。最初は重要なルールだけを有効にし、徐々に整備するのがおすすめです。
8-4. DocFXでAPIドキュメントを生成する
DocFXは、C#のXMLドキュメントコメントからAPIドキュメントを生成できるツールです。
ライブラリやSDKのドキュメントサイトを作りたい場合に便利です。XMLドキュメントコメントをもとに、クラス一覧、メソッド一覧、引数、戻り値、例外などを整理したドキュメントを生成できます。
DocFXを使う場合は、ソースコード側のコメント品質がそのままドキュメント品質に反映されます。<summary> だけでなく、<remarks> や <example> も活用すると、利用者にとってわかりやすいドキュメントになります。
8-5. Sandcastle Help File Builderで仕様書を作る
Sandcastle Help File Builderは、XMLドキュメントコメントからヘルプファイルや仕様書を作成するためのツールです。
長く使われているドキュメント生成ツールで、.NETライブラリのAPIリファレンスを作成したい場合に選択肢になります。
DocFXと同様に、元になるC#ドキュメントコメントが重要です。コメントが不足していると、生成される仕様書も不完全になります。
8-6. 自動生成ツールを使うときの注意点
ドキュメントコメントを自動生成するツールは便利ですが、生成された文章をそのまま使うだけでは不十分なことがあります。
たとえば、次のようなコメントは自動生成されがちですが、あまり役に立ちません。
C#/// <summary>
/// Gets the name.
/// </summary>
public string Name { get; }
機械的に生成されたコメントは、メンバー名を言い換えただけになりやすいです。重要なAPIについては、利用者が知りたい仕様や注意点を人間が補足する必要があります。
自動生成ツールは「下書き作成」や「書き忘れ検出」として使い、最終的な内容はレビューすることが大切です。
9. ドキュメントコメントのよくある疑問
9-1. privateメンバーにも書くべきか
privateメンバーに必ずドキュメントコメントを書く必要はありません。
privateメンバーは、そのクラスの内部実装であり、外部の利用者が直接参照するものではないためです。すべてのprivateメソッドにコメントを書くと、かえって保守コストが増えることがあります。
ただし、複雑な処理、業務ルール、注意が必要な前提条件がある場合は、コメントを書く価値があります。
C#/// <summary>
/// 請求締め日を考慮して、売上計上日を算出します。
/// </summary>
private DateTime CalculateRevenueDate(DateTime orderDate)
{
// ...
}
privateメンバーでは、ドキュメントコメントよりも通常のコメントやメソッド名の改善で対応できる場合も多いです。
9-2. 全メソッドにコメントを書く必要はあるか
全メソッドに機械的にコメントを書く必要はありません。
重要なのは、利用者にとって説明が必要なメソッドに適切なコメントを書くことです。
公開API、共通ライブラリ、複雑な業務ロジック、例外条件があるメソッド、使い方を誤りやすいメソッドには、積極的にコメントを書くべきです。
一方、単純なprivateメソッドや、名前だけで十分に意味が伝わる小さなメソッドに無理にコメントを書くと、重複した情報が増えるだけになることがあります。
9-3. コメントが長すぎる場合はどうするか
コメントが長くなりすぎる場合は、情報を整理します。
<summary> には短い概要を書き、詳細は <remarks> に分けます。
C#/// <summary>
/// 月次レポートを生成します。
/// </summary>
/// <remarks>
/// <para>
/// 売上、返品、割引を集計してレポートを作成します。
/// </para>
/// <para>
/// 集計対象は指定された年月に計上されたデータです。
/// </para>
/// </remarks>
public Report GenerateMonthlyReport(int year, int month)
{
// ...
}
さらに長い説明が必要な場合は、外部ドキュメントや設計書へのリンクを検討します。ドキュメントコメントには、APIを使うために必要な情報を簡潔にまとめるのが基本です。
9-4. <summary>だけでも問題ないか
単純なクラスやプロパティであれば、<summary> だけでも問題ありません。
C#/// <summary>
/// 商品名を取得または設定します。
/// </summary>
public string ProductName { get; set; } = string.Empty;
ただし、メソッドに引数や戻り値がある場合は、<param> や <returns> も書く方が親切です。
C#/// <summary>
/// 指定された商品の在庫数を取得します。
/// </summary>
/// <param name="productId">商品ID。</param>
/// <returns>在庫数。</returns>
public int GetStockQuantity(int productId)
{
// ...
}
例外が発生する可能性がある場合は、<exception> も追加すると利用者が安全に使えます。
9-5. nullable参照型との関係はあるか
nullable参照型を有効にしている場合、型情報からnullを許可するかどうかをある程度判断できます。
C#public User? FindUser(int id)
この場合、戻り値が User? なので、nullが返る可能性があることは型からわかります。
ただし、「どのような場合にnullになるのか」は型だけではわかりません。ドキュメントコメントで補足すると、より親切です。
C#/// <summary>
/// 指定されたIDのユーザーを検索します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザーが存在する場合はユーザー情報。それ以外の場合は null。</returns>
public User? FindUser(int id)
{
// ...
}
nullable参照型はドキュメントコメントの代わりではなく、補完し合うものと考えるとよいでしょう。
9-6. SwaggerやOpenAPIとは関係あるか
ASP.NET CoreでWeb APIを開発している場合、C#ドキュメントコメントはSwaggerやOpenAPIの説明に利用できることがあります。
たとえば、コントローラーやアクションメソッドにコメントを書き、XMLドキュメントファイルを生成してSwagger設定で読み込むと、API仕様書に説明を表示できます。
C#/// <summary>
/// 指定されたIDのユーザーを取得します。
/// </summary>
/// <param name="id">ユーザーID。</param>
/// <returns>ユーザー情報。</returns>
[HttpGet("{id}")]
public ActionResult<UserResponse> GetUser(int id)
{
// ...
}
Web APIでは、利用者がエンドポイントの仕様を理解しやすくなるため、ドキュメントコメントを書くメリットが大きくなります。
ただし、SwaggerやOpenAPIに反映するには、XMLドキュメントファイルの生成とSwagger側の読み込み設定が必要です。
9-7. XMLコメントがIntelliSenseに表示されないときの確認点
XMLコメントがIntelliSenseに表示されない場合は、次の点を確認します。
・対象のメンバー直前に /// で書いているか
・XMLタグが正しく閉じられているか
・param の name が実際の引数名と一致しているか
・参照しているライブラリに XML ドキュメントファイルが含まれているか
・DLL と XML ファイルが同じ場所に配置されているか
・IDE側のキャッシュや解析が古くなっていないか
特に、別プロジェクトやNuGetパッケージとして参照している場合、DLLだけでなくXMLドキュメントファイルも必要になることがあります。
ライブラリ側でXMLドキュメントファイルを生成していない場合、利用側のIntelliSenseにコメントが表示されません。
まとめ
C#ドキュメントコメントは、/// とXMLタグを使って、クラスやメソッド、プロパティなどの説明を書くための仕組みです。
基本は <summary> で概要を書き、引数には <param>、戻り値には <returns>、例外には <exception>、補足には <remarks>、使用例には <example> を使います。ジェネリック型では <typeparam>、関連メンバーの参照には <see> や <seealso>、コメントの継承には <inheritdoc> も活用できます。
XMLドキュメントファイルを生成すれば、IntelliSense、NuGetパッケージ、API仕様書、Swagger、DocFXなどと連携できます。公開ライブラリやチーム開発では、ドキュメントコメントの有無が使いやすさや保守性に大きく影響します。
一方で、すべてのメンバーに機械的なコメントを書く必要はありません。重要なのは、利用者が正しく使うために必要な情報を書くことです。メソッド名を繰り返すだけのコメントを避け、引数、戻り値、例外、nullの扱い、単位、制約、副作用などを具体的に記述しましょう。
CS1591などの警告が出る場合は、コメントを追加する、公開範囲を見直す、必要に応じて NoWarn や #pragma で抑制するなど、プロジェクトに合った方法で管理します。
C#ドキュメントコメントは、コードの利用者に対する説明書です。読みやすく、正確で、実装と一致したコメントを保つことで、開発効率とコード品質の両方を高めることができます。

