C#
.NET
exceptions
documentation
error handling

How to document thrown exceptions in c/.net

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In C# and .NET, exceptions thrown by a method should be documented using the <exception> XML documentation tag. This tells consumers of the API exactly which exceptions they need to handle and under what conditions they occur. Unlike Java's checked exceptions, C# does not enforce exception handling at compile time, making documentation the primary way developers communicate exception contracts. Tools like Visual Studio IntelliSense, Sandcastle, and DocFX use these tags to generate readable API documentation.

The <exception> XML Tag

csharp
1/// <summary>
2/// Retrieves a user by their unique identifier.
3/// </summary>
4/// <param name="userId">The unique identifier of the user.</param>
5/// <returns>The user object.</returns>
6/// <exception cref="ArgumentNullException">
7/// Thrown when <paramref name="userId"/> is null or empty.
8/// </exception>
9/// <exception cref="UserNotFoundException">
10/// Thrown when no user exists with the specified ID.
11/// </exception>
12/// <exception cref="DatabaseException">
13/// Thrown when the database connection fails.
14/// </exception>
15public User GetUser(string userId)
16{
17    if (string.IsNullOrEmpty(userId))
18        throw new ArgumentNullException(nameof(userId));
19
20    var user = _repository.FindById(userId)
21        ?? throw new UserNotFoundException($"User '{userId}' not found.");
22
23    return user;
24}

Each <exception> tag specifies the exception type via cref and explains the condition under which it is thrown.

Documenting Multiple Exceptions

A method may throw several different exceptions. Document each one separately:

csharp
1/// <summary>
2/// Writes content to a file at the specified path.
3/// </summary>
4/// <param name="path">The file path to write to.</param>
5/// <param name="content">The content to write.</param>
6/// <exception cref="ArgumentNullException">
7/// Thrown when <paramref name="path"/> or <paramref name="content"/> is null.
8/// </exception>
9/// <exception cref="ArgumentException">
10/// Thrown when <paramref name="path"/> is empty or contains invalid characters.
11/// </exception>
12/// <exception cref="IOException">
13/// Thrown when the file cannot be written due to a disk or permission error.
14/// </exception>
15/// <exception cref="UnauthorizedAccessException">
16/// Thrown when the caller lacks write permission to the specified path.
17/// </exception>
18public void WriteFile(string path, string content)
19{
20    ArgumentNullException.ThrowIfNull(path);
21    ArgumentNullException.ThrowIfNull(content);
22
23    if (string.IsNullOrWhiteSpace(path))
24        throw new ArgumentException("Path cannot be empty.", nameof(path));
25
26    File.WriteAllText(path, content);
27}

Interface Exception Documentation

Document exceptions on interface methods so all implementers follow the same contract:

csharp
1public interface IPaymentProcessor
2{
3    /// <summary>
4    /// Processes a payment for the specified amount.
5    /// </summary>
6    /// <param name="amount">The payment amount in cents.</param>
7    /// <exception cref="ArgumentOutOfRangeException">
8    /// Thrown when <paramref name="amount"/> is less than or equal to zero.
9    /// </exception>
10    /// <exception cref="PaymentDeclinedException">
11    /// Thrown when the payment gateway declines the transaction.
12    /// </exception>
13    /// <exception cref="PaymentTimeoutException">
14    /// Thrown when the payment gateway does not respond within the timeout period.
15    /// </exception>
16    Task<PaymentResult> ProcessAsync(int amount);
17}

Async Method Exceptions

For async methods, document both direct exceptions and exceptions wrapped in the returned Task:

csharp
1/// <summary>
2/// Fetches data from the remote API.
3/// </summary>
4/// <param name="endpoint">The API endpoint URL.</param>
5/// <exception cref="ArgumentNullException">
6/// Thrown immediately when <paramref name="endpoint"/> is null.
7/// </exception>
8/// <exception cref="HttpRequestException">
9/// Thrown (via the returned Task) when the HTTP request fails.
10/// </exception>
11/// <exception cref="TaskCanceledException">
12/// Thrown (via the returned Task) when the request exceeds the timeout.
13/// </exception>
14public async Task<string> FetchDataAsync(string endpoint)
15{
16    ArgumentNullException.ThrowIfNull(endpoint);
17
18    using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
19    var response = await client.GetAsync(endpoint);
20    response.EnsureSuccessStatusCode();
21    return await response.Content.ReadAsStringAsync();
22}

Enabling XML Documentation Generation

To generate the XML documentation file from these tags:

xml
1<!-- In your .csproj file -->
2<PropertyGroup>
3    <GenerateDocumentationFile>true</GenerateDocumentationFile>
4    <NoWarn>$(NoWarn);1591</NoWarn> <!-- Suppress missing XML comment warnings -->
5</PropertyGroup>

The generated XML file is used by IntelliSense in Visual Studio and by documentation generators like DocFX and Sandcastle.

Common Pitfalls

  • Documenting exceptions that the method does not actually throw: Only document exceptions that the method itself throws or that callers should reasonably expect from the method's direct operations. Do not document every possible exception from deep internal call chains.
  • Using generic exception types in documentation: Documenting <exception cref="Exception"> provides no useful information. Document specific exception types (ArgumentNullException, IOException, etc.) so callers know exactly what to catch.
  • Not documenting exceptions on interface methods: If only the implementation documents exceptions, consumers who program against the interface have no visibility. Document exceptions on the interface contract.
  • Forgetting that cref is validated by the compiler: The cref attribute in <exception cref="..."> is checked at compile time. Misspelling the exception type or missing a using directive produces a warning. Use the full type name or add the appropriate using statement.
  • Assuming XML docs replace proper exception handling: Documentation helps callers understand what to expect, but it does not enforce handling. Critical exception contracts should also be reinforced through clear naming, parameter validation, and unit tests that verify expected exceptions.

Summary

  • Use <exception cref="ExceptionType"> XML tags to document each exception a method can throw
  • Explain the condition that triggers each exception in the tag body
  • Document exceptions on interfaces so consumers know the contract without reading implementations
  • Enable XML documentation generation in .csproj with <GenerateDocumentationFile>true</GenerateDocumentationFile>
  • Document specific exception types, not the generic Exception base class
  • For async methods, clarify whether exceptions are thrown immediately or via the returned Task

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.