NullableCancellationToken
Diagnostic Rule Overview
Field | Value |
---|---|
ID | SHIMMER1000 |
Analyzer title | Do not use a nullable CancellationToken |
Analyzer message | CancellationToken should not be nullable |
Code fix title | Make CancellationToken non-nullable |
Default severity | Warning |
Minimum framework/language version | N/A |
Category | ShimmeringUsage |
Link to code | NullableCancellationTokenAnalyzer.cs |
Code fix exists? | Yes |
Detailed Explanation
CancellationToken
is a struct
that follows the null object pattern, and default(CancellationToken)
is CancellationToken.None
, which is a valid, non-null instance representing a non-cancellable token. See also: https://devblogs.microsoft.com/premier-developer/recommended-patterns-for-cancellationtoken/
Examples
Flagged code:
using System.Threading;
using System.Threading.Tasks;
namespace Tests;
class Test
{
Task DoAsync(CancellationToken? cancellationToken = null) => Task.CompletedTask;
}
Fixed code:
using System.Threading;
using System.Threading.Tasks;
namespace Tests;
class Test
{
Task DoAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
}
Justification of the Severity
While a nullable CancellationToken (CancellationToken?
) is syntactically valid, it promotes an anti-pattern that requires unnecessary null handling logic. There is no situation where you'd want to prefer Cancellation?
token over CancellationToken.None
.
When to Suppress
Suppress this diagnostic only if it's unmanageable to update the corresponding tests. However, you should likely be able to leverage simple string replacement (e.g. It.IsAny<CancellationToken?>()
to It.IsAny<CancellationToken>()
if your tests use Moq) to do this in tests as well.
Related Rules
- SHIMMER1001: Include a CancellationToken parameter in an asynchronous method
- CA1068: CancellationToken parameters must come last
- CA2016: Forward the CancellationToken parameter to methods that take one
Inspiration
This was inspired by Mike Cop, @madelson's internal documentation created during his time at @mastercard.