Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Sugestão
Este artigo faz parte da secção Fundamentos para programadores que já conhecem pelo menos uma linguagem de programação e estão a aprender C#. Começa com a visão geral de correspondência de moldes se os moldes forem novos para ti. Para regras completas da linguagem, veja padrões relacionais e padrões lógicos na referência da linguagem.
Padrões relacionais e lógicos descrevem intervalos, alternativas e exclusões. O método seguinte combina-os para classificar uma temperatura:
static string ClassifyTemperature(int temperature) =>
temperature switch
{
< 0 => "Below freezing",
>= 18 and <= 24 => "Comfortable",
(>= 0 and < 10) or > 30 => "Far outside the comfortable range",
_ => "Cool or warm"
};
A expressão temperature é a entrada de padrão. O C# avalia isso uma vez, e cada ramo do switch verifica o valor resultante. Os braços realizam estes testes:
-
< 0testa um limite. -
>= 18 and <= 24Testa um intervalo de valores. -
(>= 0 and < 10) or > 30testa dois campos alternativos.
Este artigo mostra tanto padrões como condições imperativas para que possa aprender cada forma e comparar como expressam as mesmas decisões. Uma única condição pode parecer semelhante em qualquer uma das formas. Os padrões podem tornar uma série de ramos relacionados mais fáceis de ler, mantendo as escolhas ao lado dos seus resultados. Escolha o formulário que torne o código mais fácil de entender.
Compare valores com padrões relacionais
Um padrão relacional compara a sua entrada de padrão com uma constante em tempo de compilação usando <, >, <=, ou >=. Uma constante de tempo de compilação é um valor que o compilador pode avaliar durante a compilação do programa. Literais numéricos e caracterais, e const variáveis de tipos numéricos ou caracterais compatíveis, são exemplos representativos. Variáveis ordinárias, propriedades, chamadas de método e static readonly campos não são constantes em tempo de compilação. No exemplo de abertura, tanto >= 18 como <= 24 testam o mesmo valor avaliado temperature .
O mesmo símbolo relacional pode aparecer numa expressão comum ou num padrão. O exemplo seguinte utiliza ambas as formas com uma temperatura:
static void ShowExpressionAndPattern(int temperature, int threshold)
{
bool belowThreshold = temperature < threshold;
bool belowFreezing = temperature is < 0;
string description = temperature switch
{
< 0 => "Freezing",
0 => "Freezing point",
> 0 => "Above freezing"
};
Console.WriteLine(
$"Below threshold: {belowThreshold}; " +
$"below freezing: {belowFreezing}; {description}");
}
temperature < threshold é uma expressão relacional. Avalia ambos os operandos e produz um bool. Qualquer um dos operandos pode ser uma expressão não constante.
Em temperature is < 0, temperature é a expressão de entrada do padrão. C# avalia-o, e o padrão < 0 relacional testa o valor resultante. No ramo switch < 0 => "Freezing", a expressão antes de switch fornece o valor de entrada, pelo que o padrão contém apenas < 0.
A expressão pode comparar temperature com a variável threshold. Um operando de padrão relacional deve ser uma constante em tempo de compilação, por isso use a expressão relacional quando o valor de comparação for uma variável. Quando o valor de comparação é constante, qualquer uma das formas pode funcionar.
Quando o operando correto está constante, escolha principalmente pela legibilidade. Uma expressão relacional muitas vezes encaixa numa comparação direta. Um padrão relacional compõe-se com outros padrões e encaixa-se naturalmente quando vários intervalos correspondem para alternar resultados.
Combinar condições com padrões lógicos
Padrões lógicos combinam ou negam padrões com os operadores de padrões and, or e not:
- Um padrão coincide quando ambos os padrões aninhados coincidem
and. - Um padrão coincide quando qualquer um dos
orpadrões aninhados coincide. - Um
notpadrão tem sucesso quando o seu padrão aninhado falha.
O exemplo inicial serve and para descrever um intervalo e or para descrever alternativas. Um not padrão pode excluir um valor, como em status is not Status.Complete. Os métodos seguintes mostram ambas as formas para que possa aprender a sua sintaxe e comparar como expressam o mesmo teste:
static bool IsWeekendPattern(DayOfWeek day) =>
day is DayOfWeek.Saturday or DayOfWeek.Sunday;
static bool IsWeekendImperative(DayOfWeek day) =>
day == DayOfWeek.Saturday || day == DayOfWeek.Sunday;
A forma do padrão usa dois padrões constantes ligados por or. A forma imperativa utiliza duas expressões de igualdade unidas pelo operador ||condicional-OU . Ambos os formulários são concisos e claros para esta única condição. Escolha o formulário que melhor se adequa ao código envolvente. Os padrões frequentemente esclarecem várias escolhas relacionadas num switch, como no exemplo inicial.
Os operadores de padrões formam padrões em vez de expressões booleanas: and corresponde à conjunção de padrões, or a alternativas de padrões e not à negação de padrões. As expressões booleanas usam &&, ||, e !. Escolhe or quando várias alternativas de padrão têm o mesmo resultado. Escolha not quando expressar o padrão excluído é mais claro do que listar todos os valores aceites.
Padrões de grupo com parênteses
Um padrão entre parênteses usa parênteses para mostrar ou alterar como os padrões aninhados são agrupados. A associação determina quais os operandos de padrão que um operador agrupa em conjunto, tal como no agrupamento implícito quando não se escrevem os parênteses. C# especifica a seguinte ordem de ligação:
notandor
O teste seguinte aceita as prioridades 1 a 3 ou a prioridade especial 9:
static bool IsAcceptedPriority(int priority) =>
priority is (>= 1 and <= 3) or 9;
O compilador agrupa and antes de or. Os parênteses tornam explícito o agrupamento pretendido e as duas alternativas fáceis de ver: o intervalo de 1 a 3, ou 9. Para facilitar a leitura, use parênteses sempre que um padrão combinar and e or, ou quando not se aplicar a um padrão composto. Parênteses também podem alterar o agrupamento padrão, como em not (>= 1 and <= 3).
A ordem de verificação em tempo de execução para padrões aninhados não é especificada, e os operadores de padrões seguem regras de correspondência de padrões em vez de regras booleanas de curto-circuito. Escreve padrões aninhados para que o resultado seja independente da ordem de verificação.
Use um when protetor para uma condição separada
Os padrões lógicos funcionam melhor quando padrões aninhados descrevem o próprio valor de entrada. Uma when guarda é uma condição booleana adicional numa case etiqueta ou braço de comutação. Usa uma guarda quando a decisão também depende de informação separada da entrada do padrão.
O seguinte aviso depende da temperatura e de um valor separado isOutdoors :
static string GetHeatWarning(int temperature, bool isOutdoors) =>
temperature switch
{
> 35 when isOutdoors => "High heat outdoors",
> 35 => "High heat",
_ => "No heat warning"
};
O padrão > 35 relacional descreve a temperature entrada. O guarda when isOutdoors verifica um valor separado. Uma cláusula de guarda também é preferível quando a condição exige uma chamada de método ou uma expressão booleana que a sintaxe de padrões não exprime claramente.
Use padrões relacionais e lógicos quando facilitem a visualização das formas ou valores permitidos pela entrada, especialmente em vários braços de comutação. Use uma expressão booleana comum quando estipula uma condição direta de forma mais simples. Use uma when guarda quando a escolha de um interruptor depende de um valor separado ou de uma condição melhor expressa como uma expressão booleana.