Descarta e o padrão de descarte

Dica

Este artigo faz parte da seção Conceitos Básicos para desenvolvedores que já conhecem pelo menos uma linguagem de programação e estão aprendendo C#. Se você for novo nos padrões, comece com a visão geral da correspondência de padrões. Para obter a sintaxe completa, consulte a referência de padrão de descarte.

O token de sublinhado (_) comunica que um valor não é necessário. Seu significado exato depende de onde ele aparece:

Context Significado de _
Um ramo de uma expressão switch ou um padrão aninhado Um padrão de descarte que corresponde sem capturar o resultado
Uma desconstrução ou um out argumento Um descarte que ignora um valor produzido
Uma atribuição como _ = expression Uma atribuição de descarte que avalia a expressão e ignora seu resultado
Dois ou mais parâmetros lambda nomeados _ Descartar parâmetros cujas entradas não são usadas
var _ em um padrão Um padrão var com uma designação de descarte

Esses formulários compartilham ortografia e intenção, mas não são intercambiáveis.

Correspondência de padrões com switch

No seguinte exemplo, statusCode é um int. Cada ramo do switch produz uma mensagem string, que o programa escreve no console. O _ final trata todos os códigos de status, exceto 200 e 404:

static void ShowStatus()
{
    int statusCode = 503;
    string message = statusCode switch
    {
        200 => "Ready",
        404 => "Not found",
        _ => "Another status"
    };

    Console.WriteLine(message);
}

Um padrão de descarte é aplicado a uma expressão de entrada. O C# avalia a expressão e _ corresponde ao valor avaliado sem capturá-la. Escolha _ como o ramo final da expressão switch quando todos os valores não tratados anteriormente devem usar a mesma alternativa padrão. Coloque-o por último porque corresponde a qualquer coisa, incluindo null.

A forma var _ está na forma de um padrão var com uma designação de descarte. Ele também corresponde a todos os valores avaliados, mas não introduz uma variável legível. Prefira o padrão de descarte mais curto _ para um catch-all de comutador. Para obter mais informações sobre var padrões e designações, consulte Declaração, constante e var padrões.

Declarações de desestruturação

GetForecast retorna uma tupla com quatro componentes: uma string cidade e três int valores para a alta temperatura, baixa temperatura e chance de chuva. A declaração de desconstrução mantém city e high porque o programa as exibe. Ele usa _ para a baixa temperatura e a chance de chuva porque nomear esses componentes não utilizados implicaria que o código precisa deles:

static void ShowForecast()
{
    var (city, high, _, _) = GetForecast();
    Console.WriteLine($"{city}: high {high}°C");

    static (string City, int High, int Low, int RainChance) GetForecast() =>
        ("Portland", 18, 9, 40);
}

A mesma sintaxe de descarte funciona quando o método Deconstruct de um objeto produz vários valores. Para essas formas, consulte Desconstrução de tuplas e outros tipos.

Chamadas para métodos com parâmetros out

Suponha que um campo de entrada aceite texto somente quando ele representa um número inteiro. O TryParse(String, Int32) método retorna um bool que relata se a análise foi bem-sucedida. Ele também produz o int analisado por meio do parâmetro out. O código a seguir precisa apenas do resultado booliano para aceitar ou rejeitar a entrada:

static void CheckInput()
{
    string text = "42";

    if (IsWholeNumber(text))
    {
        Console.WriteLine($"Accepted: {text}");
    }
    else
    {
        Console.WriteLine("Enter a whole number.");
    }

    static bool IsWholeNumber(string text) => int.TryParse(text, out _);
}

Use out _ quando apenas o sucesso da operação for importante. O descarte deixa claro que o número analisado não é necessário. Se o código posterior precisar do número, dê um nome ao out argumento, como out int number, e mantenha esse valor em vez disso.

Uma atribuição de descarte, _ = expression, avalia uma expressão e ignora intencionalmente seu resultado. Às vezes, isso é útil quando a expressão, de outro modo, não seria uma instrução válida.

Important

Não use _ = Task.Run(...) ou _ = SomeAsyncMethod() para descartar uma tarefa no código da aplicação. Aguarde a tarefa para que sua conclusão e exceções permaneçam no fluxo de chamada. Uma atribuição de descarte não torna uma tarefa segura, não trata sua exceção nem cria uma operação fire-and-forget compatível.

Marcar parâmetros lambda não utilizados

Um EventHandler recebe um object? remetente e um EventArgs valor. O manipulador a seguir não precisa de nenhum parâmetro; ele grava apenas "Timer tick" no console. Nomear ambos os parâmetros _ torna seu status não utilizado visível sem inventar nomes que o corpo nunca usa:

static void ShowLambdaDiscards()
{
    EventHandler handler = (_, _) => Console.WriteLine("Timer tick");
    handler(null, EventArgs.Empty);
}

Escolha os parâmetros de descarte quando uma assinatura delegada exigir entradas que o corpo lambda não usa. Se um lambda tiver apenas um parâmetro nomeado _, _ permanecerá um nome de parâmetro comum para compatibilidade com versões anteriores.

Evitar _ como um identificador

_ pode ser um identificador comum em contextos em que O C# não reconhece um descarte. Uma variável no escopo nomeada _ pode receber uma atribuição que se parece com uma atribuição de descarte. Em um contexto de padrão, uma constante acessível ou tipo nomeado _ também pode alterar o modo como _ é interpretado. Evite declarar suas próprias variáveis, constantes ou tipos nomeados _; use _ para comunicar a intenção de descarte.

Consulte também