Поделиться через


CA2012: правильно используйте ValueTasks

Свойство Значение
Идентификатор правила CA2012
Заголовок используйте ValueTasks правильно
Категория Надежность
Исправление является критическим или не критическим Не критическое
Включен по умолчанию в .NET 10 Как предложение

Причина

Экземпляр ValueTask, возвращенный из вызова члена, используется способом, который может привести к возникновению исключений, повреждению или ухудшению производительности.

Описание правила

Экземпляры ValueTask, возвращаемые из вызовов членов, предназначены для непосредственного ожидания. Попытки использовать ValueTask несколько раз или для прямого доступа к результату до его завершения могут привести к возникновению исключения или повреждения. Игнорирование ValueTask, скорее всего, указывает на функциональную ошибку и может привести к снижению производительности.

Устранение нарушений

Как правило, экземпляры ValueTask следует ожидать непосредственно, а не отменять или хранить в других местах, таких как локальные переменные или поля.

Когда лучше отключить предупреждения

Для ValueTask объектов, возвращаемых из произвольных вызовов членов, вызывающий объект должен предполагать, что ValueTask необходимо использовать (например, ожидалось) один раз и только один раз. Однако если разработчик также управляет вызовом члена и имеет полное знание о своей реализации, разработчик может знать, что это безопасно для подавления предупреждения, например, если возврат ValueTask всегда упаковывает 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;

        // ...
    }
}

Отключение предупреждений

Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.

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

Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none в файле конфигурации.

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

Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.

См. также