diff --git a/docs/fundamentals/code-analysis/quality-rules/ca2012.md b/docs/fundamentals/code-analysis/quality-rules/ca2012.md index d49c77d33b139..4109632a6e8aa 100644 --- a/docs/fundamentals/code-analysis/quality-rules/ca2012.md +++ b/docs/fundamentals/code-analysis/quality-rules/ca2012.md @@ -10,6 +10,8 @@ helpviewer_keywords: - "CA2012" author: stephentoub ms.author: stoub +dev_langs: +- CSharp --- # CA2012: Use ValueTasks correctly @@ -37,6 +39,10 @@ In general, ValueTasks should be directly awaited rather than discarded or store For `ValueTask` objects returned from arbitrary member calls, the caller needs to assume that the `ValueTask` must be consumed (for example, awaited) once and only once. However, if the developer also controls the member being invoked and has complete knowledge of its implementation, the developer may know it's safe to suppress the warning, for example, if the return `ValueTask` always wraps a object. +## Example + +:::code language="csharp" source="snippets/csharp/all-rules/ca2012.cs" id="snippet1"::: + ## Suppress a warning If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule. diff --git a/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2012.cs b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2012.cs new file mode 100644 index 0000000000000..7e27fc35ea61e --- /dev/null +++ b/docs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca2012.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; + +namespace ca2012 +{ + // + public class NumberValueTask + { + public async ValueTask GetNumberAsync() + { + await Task.Delay(100); + return 123; + } + + public async Task UseValueTaskIncorrectlyAsync() + { + // This code violates the rule, + // because ValueTask is awaited multiple times + ValueTask numberValueTask = GetNumberAsync(); + + int first = await numberValueTask; + int second = await numberValueTask; // <- illegal reuse + + // ... + } + + // This code satisfies the rule. + public async Task UseValueTaskCorrectlyAsync() + { + int first = await GetNumberAsync(); + int second = await GetNumberAsync(); + + // .. + } + + public async Task UseValueTaskAsTaskAsync() + { + ValueTask numberValueTask = GetNumberAsync(); + + Task numberTask = numberValueTask.AsTask(); + + int first = await numberTask; + int second = await numberTask; + + // ... + } + } + // +}