Sundstrom.CheckedExceptions
1.9.8
See the version list below for details.
dotnet add package Sundstrom.CheckedExceptions --version 1.9.8
NuGet\Install-Package Sundstrom.CheckedExceptions -Version 1.9.8
<PackageReference Include="Sundstrom.CheckedExceptions" Version="1.9.8"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Sundstrom.CheckedExceptions" Version="1.9.8" />
<PackageReference Include="Sundstrom.CheckedExceptions"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Sundstrom.CheckedExceptions --version 1.9.8
#r "nuget: Sundstrom.CheckedExceptions, 1.9.8"
#:package Sundstrom.CheckedExceptions@1.9.8
#addin nuget:?package=Sundstrom.CheckedExceptions&version=1.9.8
#tool nuget:?package=Sundstrom.CheckedExceptions&version=1.9.8
Checked Exceptions for C#
Take control of exception flow β enforce explicit handling or declaration in C#
β FAQ β’ π§ͺ Sample project β’ π Documentation β’ π Change Log
Demo
Click the image to watch the video om YouTube.
<a href="https://www.youtube.com/watch?v=ldJjMrqB8X4"><img src="screenshots/Screenshot3.png" alt="Video" width="500" /></a>
There are other videos in this playlist.
π What It Does
CheckedExceptions is a Roslyn analyzer that makes exception handling explicit and reveals how exceptions propagate through your code.
If a method might throw an exception, the caller must either:
- π§― Handle it (with
try/catch), or - π£ Declare it (with
[Throws(typeof(...))])
β Inspired by Javaβs checked exceptions<br /> βοΈ Fully opt-in<br /> π‘ Analyzer warnings by default β can be elevated to errors<br /> π Supports .NET and third-party libraries via XML documentation<br /> π Includes code fixes to help you quickly handle or declare exceptions<br />
β Quick Example
public class Sample
{
public void Execute()
{
// β οΈ THROW001: Unhandled exception type 'InvalidOperationException'
Perform();
}
[Throws(typeof(InvalidOperationException))]
public void Perform()
{
throw new InvalidOperationException("Oops!");
}
}
βοΈ Fix it by handling:
public void Execute()
{
try { Perform(); }
catch (InvalidOperationException) { /* handle */ }
}
Or by declaring:
[Throws(typeof(InvalidOperationException))]
public void Execute()
{
Perform();
}
π§ Why Use It?
- Avoid silent exception propagation
- Document intent with
[Throws]instead of comments - Enforce better error design across your codebase
- Works with unannotated .NET methods via XML docs
- Plays nice with nullable annotations
- Avoid confusing [Throws] with
<exception>β enforce contracts, not just documentation
π¦ Installation
dotnet add package Sundstrom.CheckedExceptions
And define ThrowsAttribute in your project:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Delegate | AttributeTargets.Property, AllowMultiple = true)]
public class ThrowsAttribute : Attribute
{
public List<Type> ExceptionTypes { get; } = new();
public ThrowsAttribute(Type exceptionType, params Type[] others) { β¦ }
}
Find the full definition here.
βοΈ Configuration
.editorconfig
dotnet_diagnostic.THROW001.severity = warning
dotnet_diagnostic.THROW003.severity = warning
.csproj
<PropertyGroup>
<WarningsAsErrors>nullable,THROW001</WarningsAsErrors>
</PropertyGroup>
JSON Settings
Add CheckedExceptions.settings.json:
{
// Exceptions to completely ignore during analysis (Glob pattern).
"ignoredExceptions": [
"System.*",
"System.ArgumentNullException",
"!System.InvalidOperationException"
],
// Exceptions to ignore but still report as informational diagnostics.
"informationalExceptions": {
"System.IO.IOException": "Propagation",
"System.TimeoutException": "Always"
},
// If true, exceptions will not be read from XML documentation (default: false).
"disableXmlDocInterop": false,
// If true, control flow analysis, with redundancy checks, is disabled (default: false).
"disableControlFlowAnalysis": false,
// If true, basic redundancy checks are available when control flow analysis is disabled (default: false).
"enableLegacyRedundancyChecks": false
}
Control flow analysis powers redundancy checks (e.g. unreachable code, redundant catches, unused exception declarations). Disabling it may improve analyzer performance slightly at the cost of precision.
Register in .csproj:
<ItemGroup>
<AdditionalFiles Include="CheckedExceptions.settings.json" />
</ItemGroup>
π Diagnostics
| ID | Message |
|---|---|
THROW001 |
β Unhandled exception: must be caught or declared |
THROW002 |
βΉοΈ Ignored exception may cause runtime issues |
THROW003 |
π« Avoid declaring exception type System.Exception |
THROW004 |
π« Avoid throwing exception base type System.Exception |
THROW005 |
π Duplicate declarations of the same exception type in [Throws] |
THROW006 |
𧬠Incompatible Throws declaration (not declared on base member) |
THROW007 |
𧬠Missing Throws declaration for base member's exception |
THROW008 |
π¦ Exception already handled by declaration of super type in [Throws] |
THROW009 |
π§Ή Redundant catch typed clause |
THROW010 |
β οΈ [Throws] is not valid on full property declarations |
THROW011 |
π Exception in XML docs is not declared with [Throws] |
THROW012 |
π§Ή Redundant exception declaration (declared but never thrown) |
THROW013 |
π§Ή Redundant catch-all clause (no remaining exceptions to catch) |
THROW020 |
π Unreachable code detected |
IDE001 |
π Unreachable code (hidden diagnostic for editor greying) |
π Code Fixes
The analyzer offers the following automated code fixes:
β Add exception declaration Adds
[Throws(typeof(...))]attribute to declare the exception, or appends exception to existing attribute. (FixesTHROW001)π§― Surround with try/catch Wraps the throwing site in a
try/catchblock. (FixesTHROW001)β Add catch to existing try block Appends a new
catchclause to an existingtry. (FixesTHROW001)π§Ή Remove redundant catch clause Removes a catch clause for an exception type that is never thrown. (Fixes
THROW009)π§ Add
[Throws]declaration from base member Ensures overridden or implemented members declare the same exceptions as their base/interface. (FixesTHROW007)π§ Add
[Throws]declaration from XML doc Converts<exception>XML documentation into[Throws]attributes. (FixesTHROW011)
β¨ Advanced Features
- Lambdas, local functions, accessors, events β full support across member kinds
- Exception inheritance analysis β understands base/derived exception relationships
- XML documentation interop β merges
[Throws]with<exception>tags from external libraries - Nullability awareness β respects
#nullable enablecontext - Standard library knowledge β recognizes common framework exceptions (e.g.
Console.WriteLineβIOException) - Control flow analysis β detects whether exceptions are reachable, flags redundant
catchclauses, and reports unreachable code caused by prior throws or returns
β Frequently Asked Questions (FAQ)
β How is this different from Java's checked exceptions?
Answer:
Java's checked exceptions are mandatory β the compiler enforces them, and every method must declare or handle them. While this promotes visibility, it also leads to friction, boilerplate, and workarounds like throws Exception.
This analyzer takes a modern, flexible approach:
- β οΈ Warnings by default, not errors β youβre in control.
- βοΈ Opt-in declaration using
[Throws]β only where it matters. - π οΈ Code fixes and suppression make adoption practical.
- π Gradual adoption β use it for new code, leave legacy code untouched.
- π― Focused on intention, not obligation β you declare what callers need to know, not what
int.Parsemight throw.
β Summary: This is exception design with intent, not enforcement by force. It improves exception hygiene without the rigidity of Javaβs model.
β Can I use <exception> XML documentation tags instead of the [Throws] attribute?
Answer:
No β for your own code, <exception> tags are not treated as semantic declarations by the analyzer. While they are useful for documentation and IntelliSense, they are not part of the C# languageβs type system and cannot be reliably analyzed or enforced.
Instead, we encourage and require the use of the [Throws] attribute for declaring exceptions in a way that is:
- Explicit and machine-readable
- Suitable for static analysis and enforcement
- Integrated with code fixes and tooling support
π§© Interoperability with external libraries
When analyzing external APIs (e.g., referenced .NET assemblies), we do recognize <exception> tags from their XML documentation β but only for interop purposes. That is:
- We treat documented exceptions from public APIs as "declared" when
[Throws]is not available. - This helps maintain compatibility without requiring upstream changes.
β οΈ Summary:
<exception>tags are respected for interop, but they are not a replacement for[Throws]in code you control.
β What about .NET Standard 2.0 support?
Answer:
The analyzer offers limited support for projects targeting .NET Standard 2.0. Youβll still get accurate diagnostics for your own code, as well as third-party libraries. However, members defined in the .NET Standard framework may not indicate which exceptions they throw.
This is due to a technical limitation: the XML documentation files for .NET Standard assemblies are often incomplete or malformed, making it impossible to extract reliable exception information.
β Recommendation: Target a modern .NET SDK (e.g., .NET 6 or later) to get full analyzer support, including framework exception annotations.
β What about LINQ support?
Answer:
Thereβs no special support for LINQ at the moment. Since LINQ queries are typically deferred and represented as expression trees or objects, itβs difficult to determine where and when exceptions will actually be thrown.
We may explore better support in the future, but for now, these cases are considered out of scope.
π€ Contributing
- Fork
- Create feature branch
- Push PR with tests & documentation
- β€οΈ
π License
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on Sundstrom.CheckedExceptions:
| Repository | Stars |
|---|---|
|
marinasundstrom/YourBrand
Prototype enterprise system for e-commerce and consulting services
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2.5.1 | 659 | 9/5/2025 |
| 2.5.0 | 137 | 9/5/2025 |
| 2.2.4 | 421 | 9/1/2025 |
| 2.2.3 | 197 | 8/24/2025 |
| 2.2.2 | 167 | 8/24/2025 |
| 2.2.1 | 101 | 8/23/2025 |
| 2.2.0 | 96 | 8/23/2025 |
| 2.1.2 | 118 | 8/22/2025 |
| 2.1.1 | 176 | 8/14/2025 |
| 2.1.0 | 169 | 8/14/2025 |
| 2.0.3 | 170 | 8/12/2025 |
| 2.0.2 | 161 | 8/10/2025 |
| 2.0.1 | 157 | 8/9/2025 |
| 2.0.0 | 215 | 8/8/2025 |
| 1.9.9 | 245 | 8/6/2025 |
| 1.9.8 | 272 | 8/5/2025 |
| 1.9.7 | 248 | 8/5/2025 |
| 1.9.6 | 246 | 8/5/2025 |
| 1.9.5 | 239 | 8/5/2025 |
| 1.9.0 | 138 | 8/3/2025 |
| 1.8.5 | 51 | 8/2/2025 |
| 1.8.2 | 62 | 8/1/2025 |
| 1.8.1 | 128 | 7/31/2025 |
| 1.8.0 | 125 | 7/31/2025 |
| 1.7.1 | 116 | 7/30/2025 |
| 1.7.0 | 119 | 7/30/2025 |
| 1.6.7 | 123 | 7/29/2025 |
| 1.6.6 | 122 | 7/29/2025 |
| 1.6.5 | 136 | 7/28/2025 |
| 1.6.4 | 137 | 7/28/2025 |
| 1.6.3 | 146 | 7/28/2025 |
| 1.6.2 | 132 | 7/28/2025 |
| 1.6.1 | 153 | 7/27/2025 |
| 1.6.0 | 162 | 7/27/2025 |
| 1.5.2 | 251 | 7/26/2025 |
| 1.5.1 | 273 | 7/26/2025 |
| 1.5.0 | 270 | 7/26/2025 |
| 1.4.3 | 255 | 7/26/2025 |
| 1.4.2 | 399 | 7/25/2025 |
| 1.4.1 | 435 | 7/25/2025 |
| 1.4.0 | 482 | 7/24/2025 |
| 1.3.6 | 539 | 7/23/2025 |
| 1.3.5 | 551 | 7/23/2025 |
| 1.3.1 | 131 | 6/28/2025 |
| 1.3.0 | 122 | 6/28/2025 |
| 1.2.6 | 148 | 4/12/2025 |
| 1.2.5 | 142 | 4/12/2025 |
| 1.2.4 | 172 | 4/11/2025 |
| 1.2.3 | 218 | 11/30/2024 |
| 1.2.2 | 134 | 11/29/2024 |
| 1.2.1 | 145 | 11/28/2024 |
| 1.2.0 | 144 | 11/27/2024 |
| 1.1.9 | 144 | 11/26/2024 |
| 1.1.8 | 145 | 11/26/2024 |
| 1.1.7 | 140 | 11/26/2024 |
| 1.1.6 | 144 | 11/25/2024 |
| 1.1.5 | 145 | 11/25/2024 |
| 1.1.4 | 150 | 11/25/2024 |
| 1.1.3 | 156 | 11/24/2024 |
| 1.1.2 | 139 | 11/24/2024 |
| 1.1.1 | 140 | 11/24/2024 |
| 1.1.0 | 149 | 11/23/2024 |
| 1.0.9 | 150 | 11/22/2024 |
| 1.0.8 | 144 | 11/22/2024 |
| 1.0.7 | 144 | 11/21/2024 |
| 1.0.6 | 149 | 11/21/2024 |
| 1.0.5 | 147 | 11/20/2024 |
| 1.0.4 | 148 | 11/19/2024 |
| 1.0.3 | 144 | 11/19/2024 |
| 1.0.2 | 153 | 11/19/2024 |
| 1.0.1 | 157 | 11/19/2024 |
| 1.0.0 | 154 | 11/19/2024 |