Compartilhar via


CA2012: Usar ValueTasks corretamente

Property Valor
ID da regra CA2012
Título Usar ValueTasks corretamente
Categoria Confiabilidade
Correção interruptiva ou sem interrupção Sem interrupção
Habilitado por padrão no .NET 10 Como sugestão

Causa

Uma instância ValueTask retornada de uma invocação de membro é usada de uma maneira que pode causar exceções, corrupção ou desempenho insatisfatório.

Descrição da regra

As instâncias ValueTask retornadas de invocações de membros deverão ser aguardadas diretamente. As tentativas de consumir uma ValueTask várias vezes ou de acessar diretamente o resultado de uma antes que ela seja concluída podem resultar em uma exceção ou corrupção. Ignorar essa ValueTask será provavelmente uma indicação de um bug funcional e poderá prejudicar o desempenho.

Como corrigir violações

Em geral, ValueTasks deverão ser aguardadas diretamente, em vez de descartadas ou armazenadas em outros locais, como variáveis ou campos locais.

Quando suprimir avisos

Para objetos ValueTask retornados de chamadas de membro arbitrárias, o chamador precisará assumir que o ValueTask deverá ser consumido (por exemplo, aguardado) uma vez e apenas uma vez. No entanto, se o desenvolvedor também controlar o membro que está sendo invocado e tiver conhecimento completo da implementação, o desenvolvedor poderá saber se é seguro suprimir o aviso, por exemplo, se o retorno ValueTask sempre encapsula um objeto Task.

Example

public class NumberValueTask
{
    public async ValueTask<int> GetNumberAsync()
    {
        await Task.Delay(100);
        return 123;
    }

    public async Task UseValueTaskIncorrectlyAsync()
    {
        // This code violates the rule,
        // because ValueTask is awaited multiple times
        ValueTask<int> 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<int> numberValueTask = GetNumberAsync();

        Task<int> numberTask = numberValueTask.AsTask();

        int first = await numberTask;
        int second = await numberTask;

        // ...
    }
}

Suprimir um aviso

Para suprimir apenas uma violação, adicione diretivas de pré-processador ao arquivo de origem a fim de desabilitar e, em seguida, reabilitar a regra.

#pragma warning disable CA2012
// The code that's violating the rule is on this line.
#pragma warning restore CA2012

Para desabilitar a regra em um arquivo, uma pasta ou um projeto, defina a severidade como none no arquivo de configuração.

[*.{cs,vb}]
dotnet_diagnostic.CA2012.severity = none

Para obter mais informações, confira Como suprimir avisos de análise de código.

Confira também