Aracılığıyla paylaş


Verileri desenlerle eşleştirme

Bu öğreticide, C# dilindeki verileri incelemek için desen eşleştirmenin nasıl kullanılacağı öğretildi. Küçük miktarlarda kod yazar, sonra bu kodu derleyip çalıştırırsınız. Öğretici, C# dilindeki farklı türleri keşfeden bir dizi ders içerir. Bu dersler size C# dilinin temellerini öğretir.

Tavsiye

Kod parçacığı bloğu "Çalıştır" düğmesini içerdiğinde, bu düğme etkileşimli pencereyi açar veya etkileşimli penceredeki mevcut kodun yerini alır. Kod parçacığında "Çalıştır" düğmesi olmadığında kodu kopyalayıp geçerli etkileşimli pencereye ekleyebilirsiniz.

Önceki öğreticilerde, yerleşik türler ve tuplelar veya kayıtlar olarak tanımladığınız türler gösterilmiştir. Bu türlerin örnekleri bir desene göre denetlenebilir. Örneğin bir desenle eşleşip eşleşmediği, programınızın gerçekleştirdiği eylemleri belirler. Aşağıdaki örneklerde, tür adlarından sonra ? olduğunu fark edeceksiniz. Bu simge, bu türün değerinin null olmasını sağlar (örneğin, bool? veya truefalseolabilirnull). Daha fazla bilgi için bakınız Nullable değer türleri. Şimdi desenleri nasıl kullanabileceğinizi keşfetmeye başlayalım.

Bir değeri eşleştirme

Bu öğreticideki tüm örneklerde, bir dizi banka işlemini virgülle ayrılmış değerler (CSV) girişi olarak temsil eden metin girişi kullanılır. Örneklerin her birinde, bir is veya switch ifadesi kullanarak kaydı bir desenle eşleştirebilirsiniz. Bu ilk örnek, her satırı , karakterine göre böler ve ardından ifadesi kullanarak ilk dize alanını "DEPOSIT" veya "WITHDRAWAL" değeriyle is. Eşleştiğinde, işlem tutarı geçerli hesap bakiyesine eklenir veya düşülür. Çalıştığını görmek için "Çalıştır" düğmesine basın:

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

Çıktıyı inceleyin. Her satırın, ilk alandaki metnin değerini karşılaştırarak işlendiğini görebilirsiniz. Yukarıdaki örnek, iki == değerin string eşit olup olmadığını test etmek için işleci kullanılarak benzer şekilde oluşturulabilir. Bir değişkeni sabitle karşılaştırmak, desen eşleştirme için temel bir yapı taşıdır. Şimdi desen eşleştirmenin parçası olan yapı taşları hakkında daha fazla bilgi edinelim.

Enumerasyon eşleşmeleri

Desen eşleştirmenin bir diğer yaygın kullanımı, bir enum türünün değerlerini eşleştirmektir. Bu sonraki örnekte giriş kayıtları işlenir ve ilk değerin bir para yatırma veya çekme işlemi belirten bir veri olduğu birenum kartuple oluşturulur. İkinci değer, işlemin değeridir. Çalıştığını görmek için "Çalıştır" düğmesine basın:

Uyarı

Kopyalayıp yapıştırmayın. Aşağıdaki örnekleri çalıştırmak için etkileşimli pencerenin sıfırlanması gerekir. Hata yaparsanız pencere kilitlenir ve devam etmek için sayfayı yenilemeniz gerekir.

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
}

Yukarıdaki örnekte, ifadenin if değerini denetlemek için bir enum deyim de kullanılır. Başka bir desen eşleştirme biçimi bir switch ifade kullanır. Şimdi söz dizimlerini ve nasıl kullanabileceğinizi inceleyelim.

ile kapsamlı eşleşmeler switch

Bir dizi if deyim, bir dizi koşulu test edebilir. Ancak derleyici, bir dizi deyimin if olup olmadığını veya daha sonraki koşulların if önceki koşullar tarafından alt sıralanmış olup olmadığını anlayamaz. İfade, switch bu özelliklerin her ikisinin de karşılanmasını sağlar ve bu da uygulamalarınızda daha az hatayla sonuçlanıyor. Deneyelim ve keşfedelim. Aşağıdaki kodu kopyalayın. Etkileşimli penceredeki iki if deyimi kopyaladığınız ifadeyle switch değiştirin. Kodu değiştirdikten sonra etkileşimli pencerenin üst kısmındaki "Çalıştır" düğmesine basarak yeni örneği çalıştırın.

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

Kodu çalıştırdığınızda aynı şekilde çalıştığını görürsünüz. Kapsama işlemini göstermek için, switch kollarını aşağıdaki kod parçacığında gösterildiği gibi yeniden sırala:

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

Anahtar kollarını yeniden sıraladıktan sonra "Çalıştır" düğmesine basın. _ ile kol her değerle eşleştiğinden, derleyici bir hata verir. Sonuç olarak, o son kol TransactionType.Withdrawal asla çalışmaz. Derleyici, kodunuzda bir sorun olduğunu söyler.

switch ifadesinde test edilen bir ifade, herhangi bir anahtar kolu ile eşleşmeyen değerler içerebilecekse, derleyici bir uyarı verir. Bazı değerler herhangi bir koşulla eşleşemezse, switch ifade kapsamlı değildir. Derleyici ayrıca, girişin bazı değerleri anahtar kollarından herhangi biriyle eşleşmiyorsa bir uyarı verir. Örneğin, _ => 0.0, satırını kaldırırsanız, herhangi bir geçersiz değer eşleşmez. Çalışma zamanında bu başarısız olur. .NET SDK'sını yükledikten ve ortamınızda programlar derledikten sonra bu davranışı test edebilirsiniz. Çevrimiçi deneyim çıkış penceresinde uyarı görüntülemez.

Tip şablonları

Bu öğreticiyi tamamlamak için desen eşleştirme için bir yapı taşı daha keşfedelim: tür deseni. Tür deseni, belirtilen türde olup olmadığını görmek için bir ifadeyi çalışma zamanında test eder. Ya bir is ifadesi ya da bir switch ifadesi ile bir tür testi kullanabilirsiniz. Şimdi geçerli örneği iki şekilde değiştirelim. İlk olarak, demet yerine işlemleri temsil eden Deposit ve Withdrawal kayıt türleri oluşturalım. Etkileşimli pencerenin en altına aşağıdaki bildirimleri ekleyin:

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

Ardından, metni ayrıştırmak ve bir dizi kayıt döndürmek için yönteminden sonra Main bu yöntemi ekleyin:

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

Son olarak yöntemindeki foreachMain döngüsünü aşağıdaki kodla değiştirin:

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

Ardından sonuçları görmek için "Çalıştır" düğmesine basın. "Nihai sürüm, girişi bir türe göre test ediyor."

Desen eşleştirme, bir ifadeyi özelliklerle karşılaştırmak için bir sözlük sağlar. Desenler ifadenin türünü, tür değerlerini, özellik değerlerini ve bunların birleşimlerini içerebilir. İfadeleri bir desenle karşılaştırmak, birden çok if karşılaştırmadan daha net olabilir. İfadeleri eşleştirmek için kullanabileceğiniz bazı desenleri keşfettiniz. Uygulamalarınızda desen eşleştirmeyi kullanmanın birçok farklı yolu vardır. İlk olarak .NET SDK'sını indirmek, makinenizde bir proje oluşturmak ve kodlamaya devam etmek için .NET sitesini ziyaret edin. Keşfettikçe, aşağıdaki makalelerde C# dilinde desen eşleştirme hakkında daha fazla bilgi edinebilirsiniz: