Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este tutorial ensina como usar a correspondência de padrões para inspecionar dados em C#. Você escreve pequenas quantidades de código e, em seguida, compila e executa esse código. O tutorial contém uma série de lições que exploram diferentes tipos de padrões suportados por C#. Estas lições ensinam os fundamentos da linguagem C#.
Neste tutorial, você:
- Lançar um Codespace no GitHub com um ambiente de desenvolvimento C#.
- Testes de dados para valores discretos.
- Compara os dados de enum com o valor.
- Cria correspondências exaustivas usando
switchexpressões. - Tipos de correspondência usando padrões de tipos.
Pré-requisitos
Deve ter um dos seguintes:
- Uma conta GitHub para usar Codespaces GitHub. Se ainda não tiver uma, pode criar uma conta gratuita no GitHub.com.
- Um computador com as seguintes ferramentas instaladas:
Corresponder a um valor
Os tutoriais anteriores demonstraram tipos internos e tipos que você define como tuplas ou registros. Pode comparar instâncias destes tipos contra um padrão. Se uma instância corresponde a um padrão determina as ações que o programa executa. Nos exemplos abaixo, vê-se ? após os nomes de tipo. Este símbolo permite que o valor deste tipo seja nulo (por exemplo, bool? pode ser true, false, ou null). Para obter mais informações, consulte Tipos de valor anulável. Vamos começar a explorar como você pode usar padrões.
Abra uma janela de navegador para os codespaces do GitHub. Crie um novo espaço de código a partir do Template .NET. Se completaste outros tutoriais desta série, podes abrir esse espaço de código.
Quando o seu espaço de código carregar, crie um novo ficheiro na pasta tutoriais chamado patterns.cs.
Abra o seu novo ficheiro.
Todos os exemplos neste tutorial usam entrada de texto que representa uma série de transações bancárias como entrada CSV (valores separados por vírgula). Em cada uma das amostras, pode compatibilizar o registo com um padrão usando uma expressão
isouswitch. Este primeiro exemplo divide cada linha do,carácter e depois compara o campo da primeira cadeia com o valor "DEPOSIT" ou "WITHDRAWAL" usando umaisexpressão. Quando corresponde, o valor da transação é adicionado ou deduzido do saldo da conta corrente. Para ver o resultado, adicione o seguinte código ao patterns.cs:string bankRecords = """ DEPOSIT, 10000, Initial balance DEPOSIT, 500, regular deposit WITHDRAWAL, 1000, rent DEPOSIT, 2000, freelance payment WITHDRAWAL, 300, groceries DEPOSIT, 700, gift from friend WITHDRAWAL, 150, utility bill DEPOSIT, 1200, tax refund WITHDRAWAL, 500, car maintenance DEPOSIT, 400, cashback reward WITHDRAWAL, 250, dining out DEPOSIT, 3000, bonus payment WITHDRAWAL, 800, loan repayment DEPOSIT, 600, stock dividends WITHDRAWAL, 100, subscription fee DEPOSIT, 1500, side hustle income WITHDRAWAL, 200, fuel expenses DEPOSIT, 900, refund from store WITHDRAWAL, 350, shopping DEPOSIT, 2500, project milestone payment WITHDRAWAL, 400, entertainment """; double currentBalance = 0.0; var reader = new StringReader(bankRecords); string? line; while ((line = reader.ReadLine()) is not null) { if (string.IsNullOrWhiteSpace(line)) continue; // Split the line based on comma delimiter and trim each part string[] parts = line.Split(','); string? transactionType = parts[0]?.Trim(); if (double.TryParse(parts[1].Trim(), out double amount)) { // Update the balance based on transaction type if (transactionType?.ToUpper() is "DEPOSIT") currentBalance += amount; else if (transactionType?.ToUpper() is "WITHDRAWAL") currentBalance -= amount; Console.WriteLine($"{line.Trim()} => Parsed Amount: {amount}, New Balance: {currentBalance}"); } }Depois, escreva o seguinte texto na janela do terminal:
cd tutorials dotnet patterns.csExamina a saída. Você pode ver que cada linha é processada comparando o valor do texto no primeiro campo.
Pode-se construir de forma semelhante a amostra anterior usando o == operador para testar se dois string valores são iguais. Comparar uma variável com uma constante é um bloco de construção básico para correspondência de padrões. Vamos explorar mais dos blocos de construção que fazem parte da correspondência de padrões.
Jogos de Enum
Outro uso comum para a correspondência de padrões é a correspondência nos valores de um enum tipo. O exemplo seguinte processa os registos de entrada para criar uma tuplo onde o primeiro valor é um enum valor que indica um depósito ou levantamento. O segundo valor é o valor da transação.
Adicione o seguinte código ao final do seu ficheiro fonte. Define a
TransactionTypeenumeração:public enum TransactionType { Deposit, Withdrawal, Invalid }Adicione uma função para analisar uma transação bancária numa tupla que contenha o tipo de transação e o valor da transação. Adicione o seguinte código antes da sua declaração do
TransactionTypeenum:static IEnumerable<(TransactionType type, double amount)> TransactionRecords(string inputText) { var reader = new StringReader(inputText); string? line; while ((line = reader.ReadLine()) is not null) { string[] parts = line.Split(','); string? transactionType = parts[0]?.Trim(); if (double.TryParse(parts[1].Trim(), out double amount)) { // Update the balance based on transaction type if (transactionType?.ToUpper() is "DEPOSIT") yield return (TransactionType.Deposit, amount); else if (transactionType?.ToUpper() is "WITHDRAWAL") yield return (TransactionType.Withdrawal, amount); } else { yield return (TransactionType.Invalid, 0.0); } } }Adicione um novo ciclo para processar os dados da transação usando a
TransactionTypeenumeração que declarou:currentBalance = 0.0; foreach (var transaction in TransactionRecords(bankRecords)) { if (transaction.type == TransactionType.Deposit) currentBalance += transaction.amount; else if (transaction.type == TransactionType.Withdrawal) currentBalance -= transaction.amount; Console.WriteLine($"{transaction.type} => Parsed Amount: {transaction.amount}, New Balance: {currentBalance}"); }
O exemplo anterior também usa uma if instrução para verificar o valor de uma enum expressão. Outra forma de correspondência de padrões usa uma switch expressão. Vamos explorar essa sintaxe e como você pode usá-la.
Correspondências exaustivas com switch
Uma série de if declarações pode testar uma série de condições. Mas, o compilador não pode dizer se uma série de if instruções sejam exaustivas ou se condições if posteriores sejam subsumidas por condições anteriores.
Exaustivo significa que uma das cláusulas if ou else na série de testes cobre todas as entradas possíveis. Se uma série de if afirmações for exaustiva, cada entrada possível satisfaz pelo menos uma if ou else oração.
Subsunção significa que uma cláusula posterior ifelse não pode ser alcançada porque cláusulas anteriores ifelse correspondem a todas as entradas possíveis. Por exemplo, no seguinte código de exemplo, uma cláusula nunca corresponde:
int n = GetNumber();
if (n < 20)
Console.WriteLine("n is less than 20");
else if (n < 10)
Console.WriteLine("n is less than 10"); // unreachable
else
Console.WriteLine("n is greater than 20");
A else if cláusula nunca coincide porque cada número inferior a 10 também é inferior a 20. A switch expressão garante que ambas as características sejam atendidas, o que resulta em menos bugs em seus aplicativos. Vamos tentar e experimentar.
Copie o código a seguir. Substitua as duas instruções
ifno loopforeachpela expressãoswitchque copiou.currentBalance += transaction switch { (TransactionType.Deposit, var amount) => amount, (TransactionType.Withdrawal, var amount) => -amount, _ => 0.0, };Digite
dotnet patterns.csna janela do terminal para executar a nova amostra.Quando você executa o código, você vê que ele funciona da mesma forma.
Para demonstrar a subsunção, reordene os braços do interruptor conforme mostrado no seguinte trecho:
currentBalance += transaction switch { (TransactionType.Deposit, var amount) => amount, _ => 0.0, (TransactionType.Withdrawal, var amount) => -amount, };Depois de reordenares os braços do interruptor, escreve
dotnet patterns.csna janela do terminal. O compilador gera um erro porque o ramo com_corresponde a todos os valores. Como resultado, esse braço final comTransactionType.Withdrawalnunca é executado. O compilador informa que algo está errado em seu código.O compilador emite um aviso se a expressão testada em uma
switchexpressão pode conter valores que não correspondem a nenhum braço de switch. Se alguns valores podem não corresponder a qualquer condição, aswitchexpressão não é exaustiva. O compilador também emite um aviso se alguns valores da entrada não corresponderem a nenhum dos braços do switch.Remova a linha com
_ => 0.0,, para que quaisquer valores inválidos não coincidam.Digite
dotnet patterns.cspara ver os resultados.O compilador emite um aviso. Os dados do teste são válidos, por isso o programa funciona. No entanto, qualquer dado inválido causaria uma falha em tempo de execução.
Padrões de tipo
Para terminar este tutorial, explore mais um bloco de construção para a correspondência de padrões: o padrão tipográfico. Um padrão de tipo testa uma expressão em tempo de execução para ver se é o tipo especificado. Você pode usar um teste de tipo com uma is expressão ou uma switch expressão. Modificar a amostra atual de duas formas. Primeiro, em vez de uma tupla, construa tipos de registo Deposit e Withdrawal que representam as transações.
Adicione as seguintes declarações no final do seu ficheiro de código:
public record Deposit(double Amount, string description); public record Withdrawal(double Amount, string description);Adicione este método pouco antes da declaração da
TransactionTypeenumeração. Analisa o texto e devolve uma série de registos:static IEnumerable<object?> TransactionRecordType(string inputText) { var reader = new StringReader(inputText); string? line; while ((line = reader.ReadLine()) is not null) { string[] parts = line.Split(','); string? transactionType = parts[0]?.Trim(); if (double.TryParse(parts[1].Trim(), out double amount)) { // Update the balance based on transaction type if (transactionType?.ToUpper() is "DEPOSIT") yield return new Deposit(amount, parts[2]); else if (transactionType?.ToUpper() is "WITHDRAWAL") yield return new Withdrawal(amount, parts[2]); } yield return default; } }Adicione o seguinte código após o último
foreachciclo:currentBalance = 0.0; foreach (var transaction in TransactionRecordType(bankRecords)) { currentBalance += transaction switch { Deposit d => d.Amount, Withdrawal w => -w.Amount, _ => 0.0, }; Console.WriteLine($" {transaction} => New Balance: {currentBalance}"); }Digite
dotnet patterns.csa janela do terminal para ver os resultados. Esta versão final testa a entrada em relação a um tipo.
A correspondência de padrões fornece um vocabulário para comparar uma expressão com características. Os padrões podem incluir o tipo da expressão, valores de tipos, valores de propriedade e combinações deles. Comparar expressões com um padrão pode ser mais claro do que comparações múltiplas if . Você explorou alguns dos padrões que pode usar para combinar expressões. Há muitas outras maneiras de usar a correspondência de padrões em seus aplicativos. Ao explorar, você pode aprender mais sobre a correspondência de padrões em C# nos seguintes artigos:
- Correspondência de padrões em C#
- Explore o tutorial de correspondência de padrões
- Cenário de correspondência de padrões
Recursos de limpeza
O GitHub apaga automaticamente o seu Codespace após 30 dias de inatividade. Completaste todos os tutoriais desta série. Para eliminar o teu Codespace agora, abre uma janela do navegador e vai aos teus Codespaces. Deves ver uma lista dos teus codespaces na janela. Selecione os três pontos (...) na entrada para o espaço de código do tutorial de aprendizado e selecione apagar.
Conteúdo relacionado
- Descarregue e instale o SDK .NET 10.
- Baixe e instale o Visual Studio Code.
- Descarregue e instale o DevKit de C#.
- Explore a secção de fundamentos de C# para saber mais sobre C#.