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.
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#. Essas lições ensinam os conceitos básicos da linguagem C#.
Dica
Quando um bloco de snippet 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 snippet não inclui um botão "Executar", você pode copiar o código e adicioná-lo à janela interativa atual.
Os tutoriais anteriores demonstraram tipos embutidos e tipos que você define como tuplas ou tipos de 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 seu programa executa. Nos exemplos abaixo, você observará ? após os nomes de tipo. Esse símbolo permite que o valor desse tipo seja nulo (por exemplo, bool? pode ser true, false ou null). Para obter mais informações, consulte tipos de valor anuláveis. Vamos começar a explorar como você pode usar padrões.
Igualar a um valor
Todos os exemplos neste tutorial usam a entrada de texto que representa uma série de transações bancárias como entrada de CSV (valores separados por vírgulas). Em cada uma das amostras, você pode corresponder o registro com um padrão usando uma expressão is ou uma expressão switch. Este primeiro exemplo divide cada linha no caractere , e, em seguida, verifica o primeiro campo da string contra o valor "DEPOSIT" ou "WITHDRAWAL" usando uma expressão is. Quando corresponde, o valor da transação é adicionado ou deduzido do saldo da conta atual. 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}");
}
}
Verifique a saída. Você pode ver que cada linha é processada comparando o valor do texto no primeiro campo. O exemplo anterior pode ser construído da mesma forma 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.
Correspondências de Enum
Outro uso comum para correspondência de padrões é corresponder aos valores de um tipo enum. Este próximo exemplo processa os registros de entrada para criar uma tupla em que a primeira entrada é um enum valor que indica um depósito ou um saque. O segundo valor é o valor da transação. Para vê-lo funcionar, pressione o botão "Executar":
Aviso
Não copie e cole. A janela interativa deve ser redefinida para executar os exemplos a seguir. Se você cometer um erro, a janela será interrompida e você precisará 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 instrução if para verificar o valor de uma expressão enum . Outra forma de correspondência de padrões usa uma switch expressão. Vamos explorar essa sintaxe e como usá-la.
Resultados exaustivos com switch
Uma série de if declarações pode avaliar uma sequência de condições. No entanto, o compilador não pode dizer se uma série de if instruções são exaustivas ou se as condições posteriores if são 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 if declarações na janela interativa pela expressão switch que você copiou. 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,
};
Ao executar o código, você verá que ele funciona da mesma forma. Para demonstrar a subsumpição, reordene os braços do comutador, conforme mostrado no trecho de código a seguir.
currentBalance += transaction switch
{
(TransactionType.Deposit, var amount) => amount,
_ => 0.0,
(TransactionType.Withdrawal, var amount) => -amount,
};
Depois de reordenar os braços do comutador, pressione o botão "Executar". O compilador gera um erro porque o ramo com _ corresponde a cada valor. Como resultado, aquele braço final com TransactionType.Withdrawal nunca é executado. O compilador informa que algo está errado em seu código.
O compilador emitirá um aviso se a expressão testada em uma switch expressão puder conter valores que não correspondem a nenhum braço de comutador. Se alguns valores não corresponderem a qualquer condição, a switch expressão não será exaustiva. O compilador também emitirá um aviso se alguns valores da entrada não corresponderem a nenhum dos braços do comutador. 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ê poderá 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 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 criar Deposit e Withdrawal tipos de registro 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 esse 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;
}
}
Por fim, substitua o foreach loop no Main método 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 várias if comparações. Você explorou alguns dos padrões que pode usar para corresponder a 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 seu computador e continuar codificando. Ao explorar, você pode saber mais sobre a correspondência de padrões em C# nos seguintes artigos: