Partager via


Mettre en correspondance les données par rapport aux modèles

Ce tutoriel vous explique comment utiliser la correspondance de modèle pour inspecter les données en C#. Vous écrivez de petites quantités de code, puis vous compilez et exécutez ce code. Le tutoriel contient une série de leçons qui explorent différents types de types en C#. Ces leçons vous enseignent les principes fondamentaux de la langue C#.

Conseil / Astuce

Lorsqu’un bloc d’extrait de code inclut le bouton « Exécuter », ce bouton ouvre la fenêtre interactive ou remplace le code existant dans la fenêtre interactive. Lorsque l’extrait de code n’inclut pas de bouton « Exécuter », vous pouvez copier le code et l’ajouter à la fenêtre interactive active.

Les didacticiels précédents ont montré les types intégrés et ceux que vous définissez sous forme de tuples ou d'enregistrements. Les instances de ces types peuvent être vérifiées par rapport à un modèle. Si une instance correspond à un modèle détermine les actions effectuées par votre programme. Dans les exemples ci-dessous, vous remarquerez ? après les noms de type. Ce symbole permet à la valeur de ce type d’être null (par exemple, bool? peut être true, false ou null). Pour plus d'informations, consultez types de valeur nullables. Commençons à explorer la façon dont vous pouvez utiliser des modèles.

Mettre en correspondance une valeur

Tous les exemples de ce didacticiel utilisent une entrée de texte qui représente une série de transactions bancaires sous forme d’entrée de valeurs séparées par des virgules (CSV). Dans chacun des exemples, vous pouvez faire correspondre l’enregistrement à un schéma en utilisant soit une expression is soit une expression switch. Ce premier exemple fractionne chaque ligne au niveau du caractère ,, puis fait correspondre le premier champ de texte à la valeur « DEPOSIT » ou « WITHDRAWAL » à l'aide d'une expression . Lorsqu’il correspond, le montant de la transaction est ajouté ou déduit du solde du compte actuel. Pour le voir fonctionner, appuyez sur le bouton « Exécuter » :

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}");
    }
}

Examinez le résultat. Vous pouvez voir que chaque ligne est traitée en comparant la valeur du texte dans le premier champ. L’exemple précédent peut être construit de la même façon à l’aide de l’opérateur == pour tester que deux string valeurs sont égales. La comparaison d’une variable à une constante est un bloc de construction de base pour la mise en correspondance des modèles. Examinons davantage les blocs de construction qui font partie de la mise en correspondance des modèles.

Correspondances d’énumération

Une autre utilisation courante de la correspondance de modèle consiste à mettre en correspondance les valeurs d'un enum type. Cet exemple traite ensuite les enregistrements d’entrée pour créer un tuple où la première valeur est une enum valeur qui note un dépôt ou un retrait. La deuxième valeur est la valeur de la transaction. Pour le voir fonctionner, appuyez sur le bouton « Exécuter » :

Avertissement

Ne pas copier-coller. La fenêtre interactive doit être réinitialisée pour exécuter les exemples suivants. Si vous faites une erreur, la fenêtre se bloque et vous devez actualiser la page pour continuer.

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
}

L’exemple précédent utilise également une if instruction pour vérifier la valeur d’une enum expression. Une autre forme de correspondance de modèle utilise une switch expression. Examinons cette syntaxe et la façon dont vous pouvez l’utiliser.

Correspondances exhaustives avec switch

Une série d’instructions if peut tester une série de conditions. Toutefois, le compilateur ne peut pas savoir si une série d’instructions if est exhaustive ou si des conditions if sont subordonnées par des conditions antérieures. L’expression switch garantit que ces deux caractéristiques sont remplies, ce qui entraîne moins de bogues dans vos applications. Essayons-le et expérimentons. Copiez le code suivant. Remplacez les deux if instructions de la fenêtre interactive par l’expression switch que vous avez copiée. Une fois que vous avez modifié le code, appuyez sur le bouton « Exécuter » en haut de la fenêtre interactive pour exécuter le nouvel exemple.

currentBalance += transaction switch
{
    (TransactionType.Deposit, var amount) => amount,
    (TransactionType.Withdrawal, var amount) => -amount,
    _ => 0.0,
};

Lorsque vous exécutez le code, vous voyez qu’il fonctionne de la même façon. Pour illustrer la sous-énumération, réorganisez les bras de commutateur comme indiqué dans l’extrait de code suivant :

currentBalance += transaction switch
{
    (TransactionType.Deposit, var amount) => amount,
    _ => 0.0,
    (TransactionType.Withdrawal, var amount) => -amount,
};

Après avoir réorganisé les bras de commutateur, appuyez sur le bouton « Exécuter ». Le compilateur émet une erreur, car le bras avec _ correspond à chaque valeur. Par conséquent, ce bras final avec TransactionType.Withdrawal ne s’exécute jamais. Le compilateur vous indique que quelque chose ne va pas dans votre code.

Le compilateur émet un avertissement si l’expression testée dans une switch expression peut contenir des valeurs qui ne correspondent à aucun bras de commutateur. Si certaines valeurs peuvent ne pas correspondre à une condition, l’expression switch n’est pas exhaustive. Le compilateur émet également un avertissement si certaines valeurs de l’entrée ne correspondent pas aux bras de commutateur. Par exemple, si vous supprimez la ligne avec _ => 0.0,, les valeurs non valides ne correspondent pas. Au moment de l’exécution, cela échouerait. Une fois que vous avez installé le Kit de développement logiciel (SDK) .NET et généré des programmes dans votre environnement, vous pouvez tester ce comportement. L’expérience en ligne n’affiche pas d’avertissements dans la fenêtre de sortie.

Modèles de type

Pour terminer ce tutoriel, nous allons explorer un autre élément constitutif de la correspondance de motifs : le modèle de type. Un modèle de type teste une expression au moment de l’exécution pour voir s’il s’agit du type spécifié. Vous pouvez utiliser un test de type avec une is expression ou une switch expression. Modifions l’exemple actuel de deux façons. Tout d’abord, au lieu d’un tuple, nous allons générer Deposit et Withdrawal enregistrer des types qui représentent les transactions. Ajoutez les déclarations suivantes en bas de la fenêtre interactive :

public record Deposit(double Amount, string description);
public record Withdrawal(double Amount, string description);

Ensuite, ajoutez cette méthode après la Main méthode pour analyser le texte et renvoyer une série d’enregistrements :

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;
    }
}

Enfin, remplacez la foreach boucle dans la Main méthode par le code suivant :

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}");
}

Ensuite, appuyez sur le bouton « Exécuter » pour afficher les résultats. Cette version finale teste l’entrée par rapport à un type.

La mise en correspondance des modèles fournit un vocabulaire pour comparer une expression par rapport aux caractéristiques. Les modèles peuvent inclure le type, les valeurs des types, les valeurs des propriétés et les combinaisons d’expressions. La comparaison d’expressions par rapport à un modèle peut être plus claire que plusieurs if comparaisons. Vous avez exploré certains des modèles que vous pouvez utiliser pour faire correspondre des expressions. Il existe de nombreuses façons d’utiliser la correspondance de modèles dans vos applications. Tout d’abord, visitez le site .NET pour télécharger le Kit de développement logiciel (SDK) .NET, créez un projet sur votre ordinateur et continuez à coder. À mesure que vous explorez, vous pouvez en savoir plus sur la correspondance des modèles en C# dans les articles suivants :