Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Padrões de declaração, constante e
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#. Comece com a visão geral de correspondência de padrões se você não tiver usado padrões C# antes. Para obter regras de idioma completas, consulte a referência de padrões.
Um padrão é aplicado a uma expressão de entrada. O C# avalia a expressão e, em seguida, o padrão testa ou captura o valor resultante. Os padrões de declaração, constante e var respondem a três perguntas práticas:
- Padrão de declaração: A expressão produziu um valor não nulo de um tipo de tempo de execução compatível? Nesse caso, declare uma variável para esse valor.
- Padrão constante: A expressão produziu um valor constante específico?
-
varpadrão: Qual valor a expressão produziu? Capture-o sem primeiro testar seu tipo ou valor.
Testar e capturar um tipo com um padrão de declaração
Um padrão de declaração consiste em um tipo e uma designação. O tipo especifica qual tipo de tempo de execução testar. A designação declara a variável que recebe o valor correspondente.
O exemplo a seguir recebe um object, portanto, a expressão pode produzir muitos tipos diferentes. O padrão de declaração permite que o branch correspondente use uma quantidade decimal sem um teste de tipo separado e conversão:
static void PrintPrice(object value)
{
if (value is decimal amount)
{
Console.WriteLine($"Price: {amount:C}");
}
}
Em value is decimal amount:
-
valueé a expressão de entrada. O C# o avalia primeiro. -
decimalé o tipo testado. O padrão corresponde quando o valor avaliado não é nulo e seu tipo de tempo de execução é compatível comdecimal. -
amounté a designação. Quando o padrão corresponde, ele declaraamounte atribui o valor decimal a ele.
O compilador controla se uma variável local recebe um valor antes que seu código o leia. Esse rastreamento é chamado de atribuição definida. Dentro do if bloco, o compilador sabe que amount foi atribuído porque o bloco é executado somente quando o padrão corresponde. O compilador produzirá um erro se o código tentar acessar amount fora do if bloco. Se value não for um decimal valor, a variável amount não será atribuída a um valor.
Escolha um padrão de declaração quando o branch correspondente precisar usar o resultado como o tipo testado. Ele combina a declaração de teste, conversão e variável, o que evita repetir a expressão ou escrever uma conversão separada.
Você também pode usar padrões de declaração quando uma expressão pode produzir vários tipos úteis:
static string FormatSensorValue(object reading) =>
reading switch
{
int count => $"Count: {count}",
double temperature => $"Temperature: {temperature:F1}°C",
string message => $"Message: {message}",
_ => "Unsupported reading"
};
Cada braço declara uma variável do tipo correspondente porque o resultado precisa do comportamento de formatação desse tipo. Um padrão de declaração corresponde somente quando o valor avaliado não é nulo e já tem um tipo de tempo de execução compatível com o tipo testado por meio das conversões permitidas para padrões.
null não tem nenhum tipo de tempo de execução para que o padrão corresponda. O padrão também não executa operadores de conversão definidos pelo usuário: é um teste de tipo e captura, não uma solicitação para converter o valor em outro tipo. Para obter as regras de compatibilidade completas, consulte Declaração e padrões de tipo.
Corresponder um valor específico com um padrão constante
Um padrão constante testa se uma expressão produz uma constante específica, como um número, cadeia de caracteres, booliano, membro enumerado, valor declarado const ou null.
Os padrões constantes se ajustam a uma expressão de comutador quando vários valores conhecidos produzem um resultado diferente:
static string GetCommandMessage(Command command) =>
command switch
{
Command.Start => "Starting",
Command.Stop => "Stopping",
Command.Pause => "Pausing",
_ => "Unknown command"
};
Command é uma enumeração, um tipo que define um conjunto de constantes nomeadas.
Command.Start, Command.Stop e Command.Pause são seus membros do enum, portanto, cada ramo do switch usa um padrão constante para testar um valor nomeado do comando.
Escolha esse formulário quando o comando puder ter vários significados discretos. Os ramos do switch mantêm juntos os valores e seus resultados. Para uma comparação de igualdade simples, uma instrução if como if (command == Command.Start) geralmente é mais fácil de ler.
A correspondência por padrão constante usa regras internas da linguagem para igualdade, em vez de um operador == definido pelo usuário. Para obter as regras de igualdade e conversão detalhadas, consulte a referência de padrão constante.
O null padrão constante é útil para uma verificação nula confiável:
static bool HasText(string? text) => text is not null;
Escolha is null ou is not null quando estiver verificando o estado nulo. Esses padrões não chamam um operador de igualdade definido pelo usuário, mesmo quando o tipo da expressão sobrecarrega ==.
Capturar um resultado para um guarda com um var padrão
Um var padrão corresponde a cada resultado, incluindo null, e declara uma variável cujo tipo é o tipo de tempo de compilação da expressão de entrada. Ele pode capturar um valor computado enquanto outro padrão já está correspondendo a um objeto:
static string GetDeliveryMessage(object delivery) =>
delivery switch
{
ExpressDelivery express
when EstimateDays(express) is var days && days <= 2
=> $"Arrives in {days} day{(days == 1 ? "" : "s")}",
ExpressDelivery => "Express delivery for your location takes more than two days",
_ => "Standard delivery"
};
static int EstimateDays(ExpressDelivery delivery) =>
delivery.MilesAway <= 500 ? 1 :
delivery.MilesAway <= 1_000 ? 2 : 3;
record ExpressDelivery(int MilesAway);
O padrão ExpressDelivery express de declaração captura primeiro o objeto de entrega como express. A chamada de método EstimateDays(express) é a expressão de entrada para o padrão var. O C# avalia essa chamada de método e var days captura a estimativa resultante como days sem testar seu tipo ou valor. A estimativa pode ser de um ou dois dias quando o guarda for bem-sucedido. O resultado do braço precisa do valor capturado para relatar o número real de dias.
Uma variável local comum não pode ser declarada entre um padrão switch-arm e sua proteção when . Chamar EstimateDays(express) novamente no resultado repetiria o cálculo. Escolha esta var forma de padrão quando o código já estiver fazendo a correspondência, e tanto a guarda quanto o resultado precisarem de um valor intermediário calculado.
Se você não precisar do valor capturado, use o padrão _de descarte em vez de declarar uma variável.