Exhaustion 1.0.0
dotnet add package Exhaustion --version 1.0.0
NuGet\Install-Package Exhaustion -Version 1.0.0
<PackageReference Include="Exhaustion" Version="1.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Exhaustion" Version="1.0.0" />
<PackageReference Include="Exhaustion"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Exhaustion --version 1.0.0
#r "nuget: Exhaustion, 1.0.0"
#:package Exhaustion@1.0.0
#addin nuget:?package=Exhaustion&version=1.0.0
#tool nuget:?package=Exhaustion&version=1.0.0
Exhaustion Analyzer
A Roslyn analyzer that enforces exhaustive pattern matching for closed type hierarchies in C#.
What it does
This analyzer ensures that switch expressions and statements are exhaustive when matching against closed type hierarchies. A closed hierarchy is a type with:
- An abstract or record type with private/protected constructors
- At least one derived type nested within it
Features
- Detects missing cases in pattern matching
- Reports warnings when a discard pattern (
_) is used instead of explicit matching - Detects redundant default arms when all types are already matched
- Detects redundant default arms on sealed types (leaf nodes in hierarchies)
- Supports nested closed hierarchies
- Works with both switch expressions and switch statements
- Handles generic types and type parameters
Installation
Install via NuGet:
dotnet add package Exhaustion
Diagnostic ID
EXHAUSTION001: Switch expression/statement must be exhaustive for closed type hierarchies
Examples
Missing Cases
public abstract record Result<TSuccess, TError>
{
private Result() { }
public sealed record Ok(TSuccess Value) : Result<TSuccess, TError>;
public sealed record Error(TError Value) : Result<TSuccess, TError>;
}
// ❌ Error: missing Error case
var message = result switch
{
Result<int, string>.Ok(var value) => $"Success: {value}"
// Missing: Result<int, string>.Error case
};
Redundant Default Arms
// ❌ Error: redundant default arm - all cases already matched
var message = result switch
{
Result<int, string>.Ok(var value) => $"Success: {value}",
Result<int, string>.Error(var error) => $"Error: {error}",
_ => throw new InvalidOperationException() // Redundant!
};
// ✅ Correct: no default arm needed
var message = result switch
{
Result<int, string>.Ok(var value) => $"Success: {value}",
Result<int, string>.Error(var error) => $"Error: {error}"
};
Sealed Types
public abstract record HttpError<TError>
{
private HttpError() { }
public sealed record ExceptionError(Exception Exception) : HttpError<TError>;
public sealed record ErrorResponseError(TError Body, int StatusCode) : HttpError<TError>;
}
// If httpError is already known to be ErrorResponseError:
var httpError = (HttpError<string>.ErrorResponseError)!result;
// ❌ Error: redundant pattern matching on sealed type
var (body, statusCode) = httpError switch
{
HttpError<string>.ErrorResponseError(var b, var sc) => (b, sc),
_ => throw new InvalidOperationException() // Redundant!
};
// ✅ Correct: direct deconstruction
var (body, statusCode) = httpError;
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Exhaustion:
| Package | Downloads |
|---|---|
|
RestClient.Net
The safest way to make REST calls in C#. Functional HTTP client library with Result types, exhaustiveness checking, and zero exceptions. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 782 | 10/13/2025 |