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.
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 tipos em C#. Estas lições ensinam os fundamentos da linguagem C#.
Sugestão
Quando um bloco de trecho de código inclui o botão "Executar", esse botão abre a janela interativa ou substitui o código existente na janela interativa. Quando o trecho não inclui um botão "Executar", você pode copiar o código e adicioná-lo à janela interativa atual.
Os tutoriais anteriores demonstraram tipos internos e tipos que você define como tuplas ou registros. Instâncias desses tipos podem ser verificadas em relação a um padrão. Se uma instância corresponde a um padrão determina as ações que o programa executa. Nos exemplos abaixo, irá notar ? após os nomes dos tipos. 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.
Corresponder a um valor
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-se fazer a correspondência entre o registo e um padrão usando uma expressão is ou switch. Este primeiro exemplo divide cada linha no , caractere e, em seguida, faz a correspondência entre o primeiro campo de cadeia de caracteres e o valor "DEPOSIT" ou "WITHDRAWAL" usando uma is expressão. Quando corresponde, o valor da transação é adicionado ou deduzido do saldo da conta corrente. Para vê-lo funcionar, pressione o botão "Executar":
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}");
}
}
Examina a saída. Você pode ver que cada linha é processada comparando o valor do texto no primeiro campo. A amostra anterior pode ser construída de forma semelhante 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 correspondência de padrões é a correspondência com os valores de um tipo enum. Este próximo exemplo processa os registros de entrada para criar uma tupla onde o primeiro valor é um enum valor que registra um depósito ou um saque. O segundo valor é o valor da transação. Para vê-lo funcionar, pressione o botão "Executar":
Advertência
Não copie e cole. A janela interativa deve ser redefinida para executar os exemplos a seguir. Se você cometer um erro, a janela trava e você precisa atualizar a página para continuar.
public static class ExampleProgram
{
const 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
""";
public static void Main()
{
double 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}");
}
}
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);
}
}
}
}
public enum TransactionType
{
Deposit,
Withdrawal,
Invalid
}
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. 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 if na janela interativa pelas switch expressões copiadas. Depois de modificar o código, pressione o botão "Executar" na parte superior da janela interativa para executar o novo exemplo.
currentBalance += transaction switch
{
(TransactionType.Deposit, var amount) => amount,
(TransactionType.Withdrawal, var amount) => -amount,
_ => 0.0,
};
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 reordenar os braços do interruptor, pressione o botão "Executar". O compilador gera um erro porque o ramo com _ corresponde a todos os valores. Como resultado, esse braço final com TransactionType.Withdrawal nunca é executado. O compilador informa que algo está errado em seu código.
O compilador emite um aviso se a expressão testada em uma switch expressã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, a switch expressã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. Por exemplo, se você remover a linha com _ => 0.0,, quaisquer valores inválidos não corresponderão. Em tempo de execução, isso falharia. Depois de instalar o SDK do .NET e criar programas em seu ambiente, você pode testar esse comportamento. A experiência online não exibe avisos na janela de saída.
Padrões de tipo
Para concluir este tutorial, vamos explorar mais um bloco de construção para a correspondência de padrões: o padrão de tipo. 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. Vamos modificar o exemplo atual de duas maneiras. Primeiro, em vez de uma tupla, vamos construir Deposit e Withdrawal tipos de registo que representam as transações. Adicione as seguintes declarações na parte inferior da janela interativa:
public record Deposit(double Amount, string description);
public record Withdrawal(double Amount, string description);
Em seguida, adicione este método após o Main método para analisar o texto e retornar uma série de registros:
public 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;
}
}
Finalmente, substitua o ciclo foreach no método Main pelo seguinte código:
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}");
}
Em seguida, pressione o botão "Executar" 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. Primeiro, visite o site do .NET para baixar o SDK do .NET, criar um projeto em sua máquina e continuar codificando. Ao explorar, você pode aprender mais sobre a correspondência de padrões em C# nos seguintes artigos: