-
Notifications
You must be signed in to change notification settings - Fork 272
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Task / ValueTask related guidance (#230)
- Loading branch information
Showing
2 changed files
with
23 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--- | ||
rule_id: 1840 | ||
rule_category: performance | ||
title: Await `ValueTask` and `ValueTask<T>` directly and exactly once | ||
severity: 1 | ||
--- | ||
The consumption of the newer and performance related `ValueTask` and `ValueTask<T>` types is more restrictive than consuming `Task` or `Task<T>`. Starting with .NET Core 2.1 the `ValueTask<T>` is not only able to wrap the result `T` or a `Task<T>`, with this version it is also possible to wrap a `IValueTaskSource` / `IValueTaskSource<T>` which gives the developer extra support for reuse and pooling. This enhanced support might lead to unwanted side-effects, as the ValueTask-returning developer might reuse the underlying object after it got awaited. The safest way to consume a `ValueTask` / `ValueTask<T>` is to directly `await` it once, or call `.AsTask()` to get a `Task` / `Task<T>` to overcome these limitations. | ||
|
||
// OK / GOOD | ||
int bytesRead = await stream.ReadAsync(buffer, cancellationToken); | ||
|
||
// OK / GOOD | ||
int bytesRead = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); | ||
|
||
// OK / GOOD - Get task if you want to overcome the limitations exposed by ValueTask / ValueTask<T> | ||
Task<int> task = stream.ReadAsync(buffer, cancellationToken).AsTask(); | ||
|
||
Other usage patterns might still work (like saving the `ValueTask` / `ValueTask<T>` into a variable and awaiting later), but may lead to misuse eventually. Not awaiting a `ValueTask` / `ValueTask<T>` may also cause unwanted side-effects. Read more about `ValueTask` / `ValueTask<T>` and the correct usage [here](https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/). |