Eğitim: Desen eşleştirmeyi kullanarak algoritmalar oluşturun

Örüntü eşleme, bu türleri değiştirmeden diğer kitaplıklarda tanımlanan türler için işlevsellik eklemenize olanak tanır. Desenler için bir diğer kullanım, uygulamanızın gerektirdiği, genişletilmekte olan türün temel bir özelliği olmayan işlevler oluşturmaktır.

Bu eğitimde şunları öğreniyorsunuz:

  • Desen eşleştirmenin kullanılması gereken durumları tanıma.
  • Tür ve özellik değerlerine göre davranış uygulamak için desen eşleştirme ifadelerini kullanın.
  • Tam algoritmalar oluşturmak için desen eşleştirmeyi diğer tekniklerle birleştirin.

Prerequisites

Yükleme yönergeleri

Windows'ta tüm önkoşulları yüklemek için bu WinGet yapılandırma dosyasını kullanın. Zaten yüklü bir şey varsa WinGet bu adımı atlar.

  1. Dosyayı indirin ve çift tıklayarak çalıştırın.
  2. Lisans sözleşmesini okuyun, yyazın ve kabul etmek isteyip istemediğiniz sorulduğunda Enter seçin.
  3. Görev Çubuğunuzda yanıp sönen bir Kullanıcı Hesabı Denetimi (UAC) istemi alırsanız yüklemenin devam etmesi için izin verin.

Diğer platformlarda, bu bileşenlerin her birini ayrı ayrı yüklemeniz gerekir.

  1. Önerilen yükleyiciyi .NET SDK indirme sayfasından indirin ve çift tıklayarak çalıştırın. İndirme sayfası platformunuzu algılar ve platformunuz için en son yükleyiciyi önerir.
  2. Visual Studio Code giriş sayfasından en son yükleyiciyi indirin ve çift tıklayarak çalıştırın. Bu sayfa ayrıca platformunuzu algılar ve bağlantı sisteminiz için doğru olmalıdır.
  3. C# DevKit uzantısı sayfasındaki "Yükle" düğmesine tıklayın. Bu, Visual Studio kodu açar ve uzantıyı yüklemek mi yoksa etkinleştirmek mi istediğinizi sorar. "Yükle" seçeneğini belirleyin.

Desen eşleştirme senaryoları

Modern geliştirme genellikle birden çok kaynaktaki verileri tümleştirmeyi ve bu verilerden bilgileri ve içgörüleri tek bir uyumlu uygulamada sunmayı içerir. Siz ve ekibiniz gelen verileri temsil eden türleri kontrol etmiyor olabilirsiniz.

Klasik nesne odaklı tasarım yaklaşımı, uygulamanızda bu birden çok veri kaynağındaki her veri türünü temsil eden türler oluşturmayı gerektirir. Ardından uygulamanız bu yeni türlerle çalışır, devralma hiyerarşileri oluşturur, sanal metotlar oluşturur ve soyutlamaları gerçekleştirir. Bu teknikler işe yarar ve bazen en iyi araçlardır. Diğer durumlarda daha az kod yazabilirsiniz. Bazı durumlarda, veriyi onu kullanan işlemlerden ayırmak kodun daha kolay okunmasını sağlayabilir.

Bu öğreticide, tek bir senaryo için birkaç dış kaynaktan gelen verileri alan bir uygulama oluşturacak ve inceleyeceksiniz. örüntü eşlemenin bu verileri özgün sistemin parçası olmayan şekillerde kullanmak ve işlemek için verimli bir yol sağladığını görürsünüz.

Trafiği yönetmek için geçiş ücretleri ve yoğun zaman fiyatlandırması kullanan büyük bir metropol alanı düşünün. Bir aracın geçiş ücretlerini türüne göre hesaplayan bir uygulama yazarsınız. Daha sonraki geliştirmelerde araçtaki kişi sayısına göre fiyatlandırma dahil edilmiştir. Diğer geliştirmeler, saat ve haftanın gününe göre fiyatlandırma ekler.

Bu kısa açıklamadan, bu sistemi modellemek için bir nesne hiyerarşisini hızla çizebilirsiniz. Ancak verileriniz, diğer araç kayıt yönetim sistemleri gibi kaynaklar da dahil olmak üzere birden fazla kaynaktan gelir. Bu sistemler bu verileri modellemek için farklı sınıflar sağlar ve bu sistemler tek bir nesne modelini paylaşmaz. Bu öğreticide, aşağıdaki kodda gösterildiği gibi bu harici sistemlerden araç verilerini modellemek için bu basitleştirilmiş sınıfları kullanacaksınız:

namespace ConsumerVehicleRegistration
{
    public class Car
    {
        public int Passengers { get; set; }
    }
}

namespace CommercialRegistration
{
    public class DeliveryTruck
    {
        public int GrossWeightClass { get; set; }
    }
}

namespace LiveryRegistration
{
    public class Taxi
    {
        public int Fares { get; set; }
    }

    public class Bus
    {
        public int Capacity { get; set; }
        public int Riders { get; set; }
    }
}

Başlangıç kodunu dotnet/samples GitHub deposundan indirebilirsiniz. Araç sınıflarının farklı sistemlerden olduğunu ve farklı ad alanları içinde olduğunu görebilirsiniz. System.Object dışında ortak bir temel sınıf kullanamazsınız.

Desen eşleştirme tasarımları

Bu öğreticide kullanılan senaryo, desen eşleştirmenin iyi çözdüğü sorun türlerini vurgular:

  • Birlikte çalışmanız gereken nesneler, hedeflerinize uyan bir nesne hiyerarşisinde değildir. İlişkili olmayan sistemlerin parçası olan sınıflarla çalışıyor olabilirsiniz.
  • Eklediğiniz işlevsellik, bu sınıflar için temel soyutlamanın bir parçası değildir. Bir araç tarafından ödenen geçiş ücreti farklı araç türleri için değişir , ancak geçiş ücreti aracın temel işlevi değildir.

Verilerin şekli ve bu verilerdeki işlemler birlikte açıklanmamışsa, C# dilindeki desen eşleştirme özellikleri ile çalışmayı kolaylaştırır.

Temel geçiş ücreti hesaplamalarını uygula

En temel ücretli hesaplama yalnızca araç türüne bağlıdır:

  • Bir Car 2,00 dolardır.
  • Taxi 3,50 dolar.
  • A Bus 5,00 ABD doları.
  • DeliveryTruck 10,00 ABD dolarıdır.

Yeni TollCalculator sınıf oluşturun ve geçiş ücretini almak için araç türüne göre kalıp eşleştirme uygulayın. Aşağıdaki kod, TollCalculator'nin ilk uygulamasını gösterir.

using System;
using CommercialRegistration;
using ConsumerVehicleRegistration;
using LiveryRegistration;

namespace Calculators;

public class TollCalculator
{
    public decimal CalculateToll(object vehicle) =>
        vehicle switch
    {
        Car c           => 2.00m,
        Taxi t          => 3.50m,
        Bus b           => 5.00m,
        DeliveryTruck t => 10.00m,
        { }             => throw new ArgumentException(message: "Not a known vehicle type", paramName: nameof(vehicle)),
        null            => throw new ArgumentNullException(nameof(vehicle))
    };
}

Yukarıdaki kod, bildirim desenini test eden bir switch ifade (bu, switch deyimi ile aynı değildir) kullanır. Switch ifadesi önceki kodda vehicle değişkeniyle başlar ve ardından switch anahtar sözcüğü gelir. Ardından, süslü parantezlerin içinde yer alan tüm anahtar kollar geliyor. switch ifadesi, switch deyimini çevreleyen söz diziminde başka iyileştirmeler yapar. case anahtar sözcüğü atlanır ve her bir kolun sonucu bir ifadedir. Son iki kol, yeni bir dil özelliğini sergiliyor. { } durumu, önceki bir kolla eşleşmeyen boş olmayan herhangi bir nesneyle eşleşir. Bu kol, bu yönteme geçirilen yanlış türleri yakalar. { } durumu, her araç tipi için belirlenen durumların ardından gelmelidir. Durum tersine çevrilirse, { } öncelikli olacaktır. Son olarak, nullsabit desen bu yönteme ne zaman null geçirildiğini algılar. null deseni son olabilir çünkü diğer desenler yalnızca doğru türdeki null olmayan bir nesneyle eşleşir.

Bu kodu, Program.cs içinde aşağıdaki kodu kullanarak test edebilirsiniz:

using System;
using CommercialRegistration;
using ConsumerVehicleRegistration;
using LiveryRegistration;

using toll_calculator;

var tollCalc = new TollCalculator();

var car = new Car();
var taxi = new Taxi();
var bus = new Bus();
var truck = new DeliveryTruck();

Console.WriteLine($"The toll for a car is {tollCalc.CalculateToll(car)}");
Console.WriteLine($"The toll for a taxi is {tollCalc.CalculateToll(taxi)}");
Console.WriteLine($"The toll for a bus is {tollCalc.CalculateToll(bus)}");
Console.WriteLine($"The toll for a truck is {tollCalc.CalculateToll(truck)}");

try
{
    tollCalc.CalculateToll("this will fail");
}
catch (ArgumentException e)
{
    Console.WriteLine("Caught an argument exception when using the wrong type");
}
try
{
    tollCalc.CalculateToll(null!);
}
catch (ArgumentNullException e)
{
    Console.WriteLine("Caught an argument exception when using null");
}

Bu kod başlangıç projesine dahil edilmiştir ancak yorum satırına alınmıştır. Yorumları kaldırırsanız yazdıklarınızı test edebilirsiniz.

Desenlerin, kodun ve verilerin ayrı olduğu algoritmalar oluşturmanıza nasıl yardımcı olabileceğini görmeye başlıyorsunuz. switch ifadesi türü test eder ve sonuçlara göre farklı değerler üretir. Bu sadece başlangıç.

Doluluk fiyatlandırmasını ekle

Geçiş ücreti yetkilisi, araçların maksimum kapasitede seyahat etmesini teşvik etmek istiyor. Araçlarda daha az yolcu olduğunda daha fazla ücret alırlar ve daha düşük fiyatlandırma sunarak dolu araçları teşvik ederler:

  • Yolcu olmayan arabalar ve taksiler fazladan 0,50 dolar ödüyor.
  • İki yolcusu olan araba ve taksiler 0,50 ABD doları indirimden alır.
  • Üç veya daha fazla yolcusu olan araba ve taksiler 1,00 ABD doları indirimden alır.
  • %50 dolu değilse otobüsler ekstra 2,00 dolar ücret öder.
  • %90'dan fazla dolu otobüsler 1,00 ABD doları indirim alır.

Aynı anahtar ifadesinde bir özellik deseni kullanarak bu kuralları uygulayabilirsiniz. Özellik deseni, bir özellik değerini sabit bir değerle karşılaştırır. Özellik düzeni, tür belirlendikten sonra nesnenin özelliklerini inceler. Car {Passengers: 0} kendisi özyinelemeli bir desendir: Car üzerindeki dış özellik deseni, Passengers değerini test eden bir iç sabit desen içerir. Car için tek bir durum dört farklı duruma genişler:

vehicle switch
{
    Car {Passengers: 0} => 2.00m + 0.50m,
    Car {Passengers: 1} => 2.0m,
    Car {Passengers: 2} => 2.0m - 0.50m,
    Car                 => 2.00m - 1.0m,

    // ...
};

İlk üç örnek türün Car olup olmadığını test eder ve ardından Passengers özelliğinin değerini kontrol eder. her ikisi de eşleşirse, ifade değerlendirilir ve döndürülür.

Taksi durumlarını da benzer şekilde genişletebilirsiniz:

vehicle switch
{
    // ...

    Taxi {Fares: 0}  => 3.50m + 1.00m,
    Taxi {Fares: 1}  => 3.50m,
    Taxi {Fares: 2}  => 3.50m - 0.50m,
    Taxi             => 3.50m - 1.00m,

    // ...
};

Ardından, aşağıdaki örnekte gösterildiği gibi, otobüsler için durumları genişleterek doluluk kurallarını uygulayın.

vehicle switch
{
    // ...

    Bus b when ((double)b.Riders / (double)b.Capacity) < 0.50 => 5.00m + 2.00m,
    Bus b when ((double)b.Riders / (double)b.Capacity) > 0.90 => 5.00m - 1.00m,
    Bus => 5.00m,

    // ...
};

Geçiş ücreti yetkilisi, teslimat kamyonlarındaki yolcu sayısıyla ilgili değildir. Bunun yerine, kamyonların ağırlık sınıfına göre ücretli miktarı aşağıdaki gibi ayarlar:

  • 5000 lbs'nin üzerindeki kamyonlar fazladan 5,00 ABD doları ücretlendirilir.
  • 3000 lbs'nin altındaki hafif kamyonlara 2,00 ABD doları indirim verilir.

Bu kuralı aşağıdaki kodla uygulayabilirsiniz:

vehicle switch
{
    // ...

    DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m,
    DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m,
    DeliveryTruck => 10.00m,
};

Önceki kod, bir switch kolunun when yan tümcesini gösterir. Bir özellikte eşitlik dışındaki koşulları test etmek için when ifadesini kullanın. bitirdiğinizde, aşağıdaki koda çok benzeyen bir yönteminiz vardır:

vehicle switch
{
    Car {Passengers: 0}        => 2.00m + 0.50m,
    Car {Passengers: 1}        => 2.0m,
    Car {Passengers: 2}        => 2.0m - 0.50m,
    Car                        => 2.00m - 1.0m,

    Taxi {Fares: 0}  => 3.50m + 1.00m,
    Taxi {Fares: 1}  => 3.50m,
    Taxi {Fares: 2}  => 3.50m - 0.50m,
    Taxi             => 3.50m - 1.00m,

    Bus b when ((double)b.Riders / (double)b.Capacity) < 0.50 => 5.00m + 2.00m,
    Bus b when ((double)b.Riders / (double)b.Capacity) > 0.90 => 5.00m - 1.00m,
    Bus => 5.00m,

    DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m,
    DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m,
    DeliveryTruck => 10.00m,

    { }     => throw new ArgumentException(message: "Not a known vehicle type", paramName: nameof(vehicle)),
    null    => throw new ArgumentNullException(nameof(vehicle))
};

Daha önce belirtildiği gibi, bu anahtar kolları, bir özellik deseni içinde sabit bir deseni iç içe barındıran özyinelemeli desenlerdir.

İç içe anahtarlar kullanarak bu kodu daha az yinelenen hale getirebilirsiniz. Car ve Taxi, her ikisi de önceki örneklerde dört farklı kola sahiptir. Her iki durumda da, sabit bir desene beslenen bir bildirim deseni oluşturabilirsiniz. Bu teknik aşağıdaki kodda gösterilmiştir:

public decimal CalculateToll(object vehicle) =>
    vehicle switch
    {
        Car c => c.Passengers switch
        {
            0 => 2.00m + 0.5m,
            1 => 2.0m,
            2 => 2.0m - 0.5m,
            _ => 2.00m - 1.0m
        },

        Taxi t => t.Fares switch
        {
            0 => 3.50m + 1.00m,
            1 => 3.50m,
            2 => 3.50m - 0.50m,
            _ => 3.50m - 1.00m
        },

        Bus b when ((double)b.Riders / (double)b.Capacity) < 0.50 => 5.00m + 2.00m,
        Bus b when ((double)b.Riders / (double)b.Capacity) > 0.90 => 5.00m - 1.00m,
        Bus b => 5.00m,

        DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m,
        DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m,
        DeliveryTruck t => 10.00m,

        { }  => throw new ArgumentException(message: "Not a known vehicle type", paramName: nameof(vehicle)),
        null => throw new ArgumentNullException(nameof(vehicle))
    };

Önceki örnekte, bir switch ifadesini başka bir switch kolu içinde iç içe yerleştirmeniz, özellik değerini test eden alt kolları içeren Taxi ve Car kollarını tekrarlamamanız anlamına gelir. Bu teknik DeliveryTruck ve Bus kolları için kullanılmaz çünkü bu kollar ayrık değerler için değil özelliğin aralıklarını test eder.

En yüksek fiyatlandırmayı ekleme

Son özellik için ücretli geçiş idaresi zamana duyarlı yoğun saat fiyatlandırmasını eklemek istiyor. Sabah ve akşam yoğun saatlerde, geçiş ücretleri iki katına alınır. Bu kural trafiği yalnızca bir yönde etkiler: sabah şehre gelen ve akşam yoğun saatlerde giden. İş günü boyunca diğer zamanlarda, geçiş ücretleri % 50 artar. Gece geç saatlerde ve sabahın erken saatlerinde geçiş ücretleri %25 azaltılır. Hafta sonu boyunca, saat ne olursa olsun normal fiyattır. Aşağıdaki kodu kullanarak bu kuralı ifade etmek için bir dizi if ve else deyimi kullanabilirsiniz:

public decimal PeakTimePremiumIfElse(DateTime timeOfToll, bool inbound)
{
    if ((timeOfToll.DayOfWeek == DayOfWeek.Saturday) ||
        (timeOfToll.DayOfWeek == DayOfWeek.Sunday))
    {
        return 1.0m;
    }
    else
    {
        int hour = timeOfToll.Hour;
        if (hour < 6)
        {
            return 0.75m;
        }
        else if (hour < 10)
        {
            if (inbound)
            {
                return 2.0m;
            }
            else
            {
                return 1.0m;
            }
        }
        else if (hour < 16)
        {
            return 1.5m;
        }
        else if (hour < 20)
        {
            if (inbound)
            {
                return 1.0m;
            }
            else
            {
                return 2.0m;
            }
        }
        else // Overnight
        {
            return 0.75m;
        }
    }
}

Yukarıdaki kod düzgün çalışır, ancak okunması kolay değildir. Tüm giriş durumlarını ve iç içe geçmiş if deyimlerini birleştirerek kod hakkında düşünmeniz gerekir. Bunun yerine, bu özellik için desen eşleştirmeyi kullanacaksınız, ancak bunu diğer tekniklerle tümleştireceksiniz. Yönün, haftanın gününün ve saatin tüm birleşimlerini kapsayan tek bir desen eşleştirme ifadesi oluşturabilirsiniz. Sonuç karmaşık bir ifade olacaktır. Okuması zor ve anlaşılması zor olurdu. Bu, doğruluğu sağlamayı zorlaştırır. Bunun yerine, tüm bu durumları kısa bir şekilde açıklayan bir değer tanımlama grubu oluşturmak için bu yöntemleri birleştirin. Ardından, geçiş ücretinin çarpanını hesaplamak için desen eşleştirmeyi kullanın. Üç ayrı koşul içeren bir dizi.

  • Gün hafta içi veya hafta sonudur.
  • Ücretin toplandığı zaman dilimi.
  • Yön, şehrin içine ya da şehrin dışınadır.

Aşağıdaki tabloda giriş değerlerinin birleşimleri ve en yüksek fiyatlandırma çarpanı gösterilmektedir:

Gün Time Direction Premium
Hafta içi sabah acelesi inbound x 2,00
Hafta içi sabah acelesi outbound x 1,00
Hafta içi gündüz inbound x 1,50
Hafta içi gündüz outbound x 1,50
Hafta içi akşam trafiği inbound x 1,00
Hafta içi akşam trafiği outbound x 2,00
Hafta içi geceleyin inbound x 0,75
Hafta içi geceleyin outbound x 0,75
Hafta Sonu sabah acelesi inbound x 1,00
Hafta Sonu sabah acelesi outbound x 1,00
Hafta Sonu gündüz inbound x 1,00
Hafta Sonu gündüz outbound x 1,00
Hafta Sonu akşam trafiği inbound x 1,00
Hafta Sonu akşam trafiği outbound x 1,00
Hafta Sonu geceleyin inbound x 1,00
Hafta Sonu geceleyin outbound x 1,00

Üç değişkenin 16 farklı bileşimi vardır. Bazı koşulları birleştirerek son anahtar ifadesini basitleştirirsiniz.

Geçiş ücretlerini toplayan sistem, ücretin toplandığı zaman için bir DateTime yapı kullanır. Önceki tablodan değişkenleri oluşturan üye yöntemleri oluşturun. Aşağıdaki işlev, DateTime'nin bir hafta sonunu mu yoksa hafta içi gününü mü temsil ettiğini ifade etmek için desen eşleştirme anahtar ifadesi kullanır.

private static bool IsWeekDay(DateTime timeOfToll) =>
    timeOfToll.DayOfWeek switch
    {
        DayOfWeek.Monday    => true,
        DayOfWeek.Tuesday   => true,
        DayOfWeek.Wednesday => true,
        DayOfWeek.Thursday  => true,
        DayOfWeek.Friday    => true,
        DayOfWeek.Saturday  => false,
        DayOfWeek.Sunday    => false
    };

Bu yöntem doğrudur, ancak yineleniyor. Aşağıdaki kodda gösterildiği gibi basitleştirebilirsiniz:

private static bool IsWeekDay(DateTime timeOfToll) =>
    timeOfToll.DayOfWeek switch
    {
        DayOfWeek.Saturday => false,
        DayOfWeek.Sunday => false,
        _ => true
    };

Ardından, zamanı bloklara kategorilere ayırmak için benzer bir işlev ekleyin:

private enum TimeBand
{
    MorningRush,
    Daytime,
    EveningRush,
    Overnight
}

private static TimeBand GetTimeBand(DateTime timeOfToll) =>
    timeOfToll.Hour switch
    {
        < 6 or > 19 => TimeBand.Overnight,
        < 10 => TimeBand.MorningRush,
        < 16 => TimeBand.Daytime,
        _ => TimeBand.EveningRush,
    };

Her zaman aralığını ayrık bir değere dönüştürmek için özel enum eklersiniz. Ardından, GetTimeBand yöntemi ilişkisel desenleri ve mantıksal desenleri kullanır. İlişkisel desen, , , <>veya <=kullanarak >=sayısal bir değeri test etmenizi sağlar. Mantıksal desenler diğer desenleri birleştirir: or deseni, bir ifadenin bir veya daha fazla desenle eşleşip eşleşmediğini test eder, and deseni bir ifadenin iki ayrı desenle eşleşip eşleşmediğini sınar ve not deseni bir ifadenin bir desenle eşleşmediğini test eder.

Bu yöntemleri oluşturduktan sonra, fiyatlandırma primini hesaplamak için, demetin her öğesiyle eşleşen konumsal bir desen olan başka bir ifade ile switch kullanabilirsiniz. 16 kolu olan bir switch ifade oluşturabilirsiniz:

public decimal PeakTimePremiumFull(DateTime timeOfToll, bool inbound) =>
    (IsWeekDay(timeOfToll), GetTimeBand(timeOfToll), inbound) switch
    {
        (true, TimeBand.MorningRush, true) => 2.00m,
        (true, TimeBand.MorningRush, false) => 1.00m,
        (true, TimeBand.Daytime, true) => 1.50m,
        (true, TimeBand.Daytime, false) => 1.50m,
        (true, TimeBand.EveningRush, true) => 1.00m,
        (true, TimeBand.EveningRush, false) => 2.00m,
        (true, TimeBand.Overnight, true) => 0.75m,
        (true, TimeBand.Overnight, false) => 0.75m,
        (false, TimeBand.MorningRush, true) => 1.00m,
        (false, TimeBand.MorningRush, false) => 1.00m,
        (false, TimeBand.Daytime, true) => 1.00m,
        (false, TimeBand.Daytime, false) => 1.00m,
        (false, TimeBand.EveningRush, true) => 1.00m,
        (false, TimeBand.EveningRush, false) => 1.00m,
        (false, TimeBand.Overnight, true) => 1.00m,
        (false, TimeBand.Overnight, false) => 1.00m,
    };

Yukarıdaki kod çalışır, ancak basitleştirilebilir. Hafta sonu için sekiz kombinasyon da aynı geçiş ücretine sahip. Sekizini de aşağıdaki satırla değiştirebilirsiniz:

(false, _, _) => 1.0m,

Hem gelen hem de giden trafik, hafta içi gündüz ve gece saatlerinde aynı çarpana sahiptir. Bu dört anahtar kolunu aşağıdaki iki satırla değiştirebilirsiniz:

(true, TimeBand.Overnight, _) => 0.75m,
(true, TimeBand.Daytime, _)   => 1.5m,

Bu iki değişiklik sonrasında kod aşağıdaki kod gibi görünmelidir:

public decimal PeakTimePremium(DateTime timeOfToll, bool inbound) =>
    (IsWeekDay(timeOfToll), GetTimeBand(timeOfToll), inbound) switch
    {
        (true, TimeBand.MorningRush, true)  => 2.00m,
        (true, TimeBand.MorningRush, false) => 1.00m,
        (true, TimeBand.Daytime,     _)     => 1.50m,
        (true, TimeBand.EveningRush, true)  => 1.00m,
        (true, TimeBand.EveningRush, false) => 2.00m,
        (true, TimeBand.Overnight,   _)     => 0.75m,
        (false, _,                   _)     => 1.00m,
    };

Son olarak, normal fiyat uygulanan iki yoğun saati kaldırın. Bu kolları çıkardıktan sonra, _ öğesini son anahtar kolunda discard (false) ile değiştirin. Aşağıdaki tamamlanmış metodu alırsınız:

public decimal PeakTimePremium(DateTime timeOfToll, bool inbound) =>
    (IsWeekDay(timeOfToll), GetTimeBand(timeOfToll), inbound) switch
    {
        (true, TimeBand.Overnight, _) => 0.75m,
        (true, TimeBand.Daytime, _) => 1.5m,
        (true, TimeBand.MorningRush, true) => 2.0m,
        (true, TimeBand.EveningRush, false) => 2.0m,
        _ => 1.0m,
    };

Bu örnek, desen eşleştirmenin avantajlarından birini vurgular: desen dalları sırayla değerlendirilir. Önceki bir dalın sonraki durumlarınızdan birini işlemesi için bunları yeniden düzenlerseniz, derleyici ulaşılamayan kod hakkında sizi uyarır. Bu dil kuralları, önceki basitleştirmeleri kodun değişmediğinden güvenle yapmayı kolaylaştırdı.

Desen eşleştirme, bazı kod türlerini daha okunabilir hale getirir ve sınıflarınıza kod ekleyemiyorsanız nesne odaklı tekniklere alternatif sunar. Bulut, verilerin ve işlevlerin birbirinden ayrı yaşamasına neden oluyor. Verilerin şekli ve üzerindeki işlemler birlikte açıklanmamıştır. Bu öğreticide, mevcut verileri özgün işlevinden tamamen farklı şekillerde kullandınız. Desen eşleştirme, bu türleri genişletemeseniz bile bu türleri aşan işlevler yazmanızı sağlar.

Sonraki Adımlar

Tamamlanmış kodu dotnet/samples GitHub deposundan indirebilirsiniz. Desenleri kendi başınıza keşfedin ve bu tekniği normal kodlama etkinliklerinize ekleyin. Bu teknikleri öğrenmek, sorunlara yaklaşmanın ve yeni işlevler oluşturmanın başka bir yolunu sunar.

Ayrıca bkz.