Tutorial: Bangun algoritma menggunakan pattern matching

Pencocokan pola memungkinkan Anda menambahkan fungsionalitas untuk jenis yang ditentukan di pustaka lain tanpa memodifikasi jenis tersebut. Penggunaan lain dari pola adalah membuat fungsionalitas yang dibutuhkan aplikasi Anda yang bukan merupakan fitur mendasar dari jenis yang diperluas.

Dalam tutorial ini, Anda akan belajar cara:

  • Kenali situasi tempat pencocokan pola harus digunakan.
  • Gunakan ekspresi pencocokan pola untuk menerapkan perilaku berdasarkan jenis dan nilai properti.
  • Gabungkan pencocokan pola dengan teknik lain untuk membuat algoritma lengkap.

Prerequisites

Instruksi penginstalan

Pada Windows, file konfigurasi WinGet ini untuk menginstal semua prasyarat. Jika Anda sudah memiliki sesuatu yang terinstal, WinGet akan melewati langkah tersebut.

  1. Unduh file dan klik dua kali untuk menjalankannya.
  2. Baca perjanjian lisensi, ketik y, dan pilih Masukkan saat diminta untuk menerima.
  3. Jika Anda mendapatkan perintah Kontrol Akun Pengguna (UAC) yang berkedip di Taskbar Anda, izinkan penginstalan dilanjutkan.

Pada platform lain, Anda perlu menginstal masing-masing komponen ini secara terpisah.

  1. Unduh penginstal yang direkomendasikan dari halaman unduhan .NET SDK dan klik dua kali untuk menjalankannya. Halaman unduhan mendeteksi platform Anda dan merekomendasikan penginstal terbaru untuk platform Anda.
  2. Unduh penginstal terbaru dari halaman beranda Visual Studio Code dan klik dua kali untuk menjalankannya. Halaman itu juga mendeteksi platform Anda dan tautan harus benar untuk sistem Anda.
  3. Klik tombol "Instal" pada halaman ekstensi C# DevKit. Yang membuka kode Visual Studio, dan menanyakan apakah Anda ingin menginstal atau mengaktifkan ekstensi. Pilih "instal".

Skenario untuk pencocokan pola

Pengembangan modern sering mencakup mengintegrasikan data dari berbagai sumber dan menyajikan informasi dan wawasan dari data tersebut dalam satu aplikasi kohesif. Anda dan tim Anda mungkin tidak menentukan jenis yang mewakili data masuk.

Pendekatan desain berorientasi objek klasik mengharuskan pembuatan tipe dalam aplikasi Anda yang mewakili setiap jenis data dari beberapa sumber data tersebut. Kemudian, aplikasi Anda bekerja dengan jenis baru tersebut, membangun hierarki warisan, membuat metode virtual, dan mengimplementasikan abstraksi. Teknik-teknik itu berhasil, dan kadang-kadang itu adalah alat terbaik. Di lain waktu Anda dapat menulis lebih sedikit kode. Dalam beberapa kasus, memisahkan data dari operasi yang menggunakannya dapat membuat kode lebih mudah dibaca.

Dalam tutorial ini, Anda membuat dan menjelajahi aplikasi yang mengambil data masuk dari beberapa sumber eksternal untuk satu skenario. Anda melihat bagaimana pencocokan pola menyediakan cara yang efisien untuk mengonsumsi dan memproses data tersebut dengan cara yang tidak menjadi bagian dari sistem aslinya.

Pertimbangkan area metropolitan utama yang menggunakan tol dan tarif jam sibuk untuk mengelola lalu lintas. Anda menulis aplikasi yang menghitung tol untuk kendaraan berdasarkan jenisnya. Kemudian peningkatan menggabungkan harga berdasarkan jumlah penumpang di dalam kendaraan. Peningkatan lebih lanjut menambah harga berdasarkan waktu dan hari dalam seminggu.

Dari deskripsi singkat itu, Anda mungkin dengan cepat membuat sketsa hierarki objek untuk memodelkan sistem ini. Namun, data Anda berasal dari beberapa sumber lain, seperti sistem manajemen registrasi kendaraan. Sistem-sistem ini menyediakan kelas yang berbeda untuk memodelkan data tersebut, dan sistem-sistem tersebut tidak berbagi model objek tunggal. Dalam tutorial ini, Anda menggunakan kelas yang disederhanakan ini untuk memodelkan data kendaraan dari sistem eksternal ini, seperti yang ditunjukkan dalam kode berikut:

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

Anda dapat mengunduh kode awal dari repositori GitHub dotnet/sampels. Anda dapat melihat bahwa kelas kendaraan berasal dari sistem yang berbeda dan berada di namespace yang berbeda. Anda tidak dapat menggunakan kelas dasar umum selain System.Object.

Desain pencocokan pola

Skenario yang digunakan dalam tutorial ini menyoroti jenis masalah yang diselesaikan pencocokan pola dengan baik:

  • Objek yang perlu Anda kerjakan tidak berada dalam hierarki objek yang sesuai dengan tujuan Anda. Anda mungkin bekerja dengan kelas yang merupakan bagian dari sistem yang tidak terkait.
  • Fungsionalitas yang Anda tambahkan bukan bagian dari abstraksi inti untuk kelas-kelas ini. Tol yang dibayar oleh kendaraan berubah untuk berbagai jenis kendaraan, tetapi tol bukanlah fungsi inti kendaraan.

Ketika bentuk data dan operasi pada data tersebut tidak dijelaskan bersama-sama, fitur pencocokan pola di C# membuatnya lebih mudah untuk dikerjakan.

Menerapkan perhitungan dasar tol

Perhitungan tol yang paling dasar hanya bergantung pada jenis kendaraan:

  • Car seharga $2.00.
  • Taxi adalah $ 3.50.
  • Bus adalah $5.00.
  • DeliveryTruck adalah $10,00.

Buat kelas baru TollCalculator, dan terapkan pencocokan pola pada jenis kendaraan untuk mendapatkan jumlah tol. Kode berikut menunjukkan implementasi awal dari TollCalculator.

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

Kode sebelumnya menggunakan switch ekspresi (tidak sama denganswitchpernyataan) yang menguji pola deklarasi. Ekspresi switch dimulai dengan variabel, vehicle dalam kode sebelumnya, diikuti dengan kata kunci switch. Selanjutnya, semua lengan switch ada di dalam kurung kurawal. Ekspresi switch membuat penyempurnaan lain pada sintaks yang mengelilingi pernyataan switch. Kata kunci case dihilangkan, dan hasil dari setiap bagian berupa ekspresi. Dua lengan terakhir menunjukkan fitur bahasa baru. Kasus { } cocok dengan objek non-null yang tidak cocok dengan percabangan sebelumnya. Mekanisme ini menangkap tipe yang tidak sesuai yang diteruskan ke metode ini. Kasus { } harus mengikuti kasus untuk jenis kendaraan masing-masing. Jika urutan dibalik, kasus { } akan diutamakan. Akhirnya, nullpola konstan mendeteksi kapan null diteruskan ke metode ini. Pola null dapat menjadi yang terakhir karena pola lain hanya cocok dengan objek non-null dari jenis yang benar.

Anda dapat menguji kode ini dengan menggunakan kode berikut di Program.cs:

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

Kode tersebut disertakan dalam proyek starter tetapi dinonaktifkan dengan komentar. Hapus komentarnya, dan Anda dapat menguji apa yang Anda tulis.

Anda mulai melihat bagaimana pola dapat membantu Anda membuat algoritma dengan kode dan data terpisah. Ekspresi switch menguji jenis dan menghasilkan nilai yang berbeda berdasarkan hasilnya. Itu baru permulaan.

Tambahkan harga penghunian

Otoritas tol ingin mendorong kendaraan untuk melakukan perjalanan dengan kapasitas maksimum. Mereka memutuskan untuk mengenakan biaya lebih banyak ketika kendaraan memiliki lebih sedikit penumpang, dan mendorong kendaraan penuh dengan menawarkan harga yang lebih rendah:

  • Mobil dan taksi tanpa penumpang membayar tambahan $ 0,50.
  • Mobil dan taksi dengan dua penumpang mendapatkan diskon $ 0,50.
  • Mobil dan taksi dengan tiga atau lebih penumpang mendapatkan diskon $ 1,00.
  • Bus yang kurang dari 50% penuh membayar tambahan $ 2,00.
  • Bus yang lebih dari 90% penuh mendapatkan diskon $ 1,00.

Anda dapat menerapkan aturan ini dengan menggunakan pola properti dalam ekspresi switch yang sama. Pola properti membandingkan nilai properti dengan nilai konstan. Pola properti memeriksa properti objek setelah tipe ditentukan. Car {Passengers: 0} adalah pola rekursif: pola properti luar pada Car berisi pola konstanta dalam yang menguji nilai Passengers. Satu kasus untuk Car meluas ke empat kasus yang berbeda:

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,

    // ...
};

Tiga kasus pertama menguji jenis sebagai Car, lalu periksa nilai properti Passengers. Jika keduanya cocok, ekspresi dievaluasi dan mengembalikan nilai.

Anda juga dapat memperluas kasus penggunaan untuk taksi dengan cara yang sama:

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,

    // ...
};

Selanjutnya, terapkan aturan okupansi dengan memperluas sejumlah skenario pada bus, seperti yang ditunjukkan pada contoh berikut.

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,

    // ...
};

Otoritas tol tidak peduli dengan jumlah penumpang di truk pengiriman. Sebagai gantinya, mereka menyesuaikan jumlah tol berdasarkan kelas berat truk sebagai berikut:

  • Truk lebih dari 5000 lbs dikenakan biaya tambahan $ 5,00.
  • Truk ringan di bawah 3000 lbs diberi diskon $ 2,00.

Anda dapat menerapkan aturan tersebut dengan kode berikut:

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

Kode sebelumnya menunjukkan klausul when lengan pengalih. Gunakan klausa when untuk menguji kondisi selain kesetaraan pada properti. Setelah selesai, Anda memiliki metode yang terlihat seperti kode berikut:

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

Seperti disebutkan sebelumnya, cabang switch ini adalah pola rekursif, menumpuk pola konstan di dalam pola properti.

Anda dapat membuat kode ini tidak terlalu berulang dengan menggunakan pengalih bersarang. Car dan Taxi keduanya memiliki empat lengan yang berbeda dalam contoh sebelumnya. Dalam kedua kasus, Anda dapat membuat pola deklarasi yang mengalir ke pola konstanta. Teknik ini ditunjukkan dalam kode berikut:

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

Dalam sampel sebelumnya, menyarangkan ekspresi switch di dalam arm switch lain berarti Anda tidak mengulangi arm Car dan Taxi yang berisi child arm yang menguji nilai properti. Teknik ini tidak digunakan untuk lengan Bus dan DeliveryTruck karena lengan tersebut menguji rentang untuk properti, bukan nilai diskrit.

Tambahkan harga puncak

Untuk fitur terakhir, otoritas tol ingin menambahkan tarif jam sibuk berdasarkan waktu. Selama jam sibuk pagi dan sore hari, jumlah pengguna tol meningkat dua kali lipat. Aturan itu hanya mempengaruhi lalu lintas dalam satu arah: masuk ke kota di pagi hari, dan keluar di jam sibuk sore hari. Selama waktu lain selama hari kerja, tol meningkat sebesar 50%. Larut malam dan dini hari, tol berkurang 25%. Selama akhir pekan, itu adalah tingkat normal, terlepas dari waktu. Anda dapat menggunakan serangkaian pernyataan if dan else untuk mengekspresikan aturan ini menggunakan kode berikut:

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

Kode sebelumnya berfungsi dengan benar, tetapi sulit dibaca. Anda harus mengaitkan semua kasus input dan pernyataan bersarang if untuk memahami logika kode. Sebagai gantinya, Anda akan menggunakan pencocokan pola untuk fitur ini, tetapi Anda akan mengintegrasikannya dengan teknik lain. Anda dapat membangun ekspresi kecocokan pola tunggal yang mencakup semua kombinasi arah, hari dalam seminggu, dan waktu. Hasilnya akan menjadi ekspresi yang rumit. Akan sulit untuk membaca dan sulit dimengerti. Itu membuat sulit untuk memastikan kebenaran. Sebaliknya, gabungkan metode tersebut untuk membangun tuple nilai-nilai yang secara ringkas menggambarkan semua keadaan tersebut. Kemudian gunakan pencocokan pola untuk menghitung faktor pengali untuk biaya tol. Tuple berisi tiga kondisi diskret:

  • Hari itu adalah hari kerja atau akhir pekan.
  • Jangka waktu ketika tol dikumpulkan.
  • Arahnya adalah ke kota atau ke luar kota.

Tabel berikut menunjukkan kombinasi nilai input dan pengali harga puncak:

Day Time Direction Premium
Hari kerja kesibukan pagi inbound x 2.00
Hari kerja kesibukan pagi outbound x 1,00
Hari kerja waktu siang inbound x 1,50
Hari kerja waktu siang outbound x 1,50
Hari kerja kemacetan sore hari inbound x 1,00
Hari kerja kemacetan sore hari outbound x 2.00
Hari kerja larut malam inbound x 0,75
Hari kerja larut malam outbound x 0,75
Akhir pekan kesibukan pagi inbound x 1,00
Akhir pekan kesibukan pagi outbound x 1,00
Akhir pekan waktu siang inbound x 1,00
Akhir pekan waktu siang outbound x 1,00
Akhir pekan kemacetan sore hari inbound x 1,00
Akhir pekan kemacetan sore hari outbound x 1,00
Akhir pekan larut malam inbound x 1,00
Akhir pekan larut malam outbound x 1,00

Ada 16 kombinasi berbeda dari tiga variabel. Dengan menggabungkan beberapa kondisi, Anda menyederhanakan ekspresi sakelar akhir.

Sistem yang mengumpulkan tol menggunakan struktur DateTime untuk waktu ketika tol dikumpulkan. Buat metode anggota yang membuat variabel dari tabel sebelumnya. Fungsi berikut menggunakan ekspresi pengalih pencocokan pola untuk mengekspresikan apakah DateTime mewakili akhir pekan atau hari kerja:

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

Metode itu benar, tetapi berulang-ulang. Anda dapat menyederhanakannya, seperti yang ditunjukkan dalam kode berikut:

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

Selanjutnya, tambahkan fungsi serupa untuk mengategorikan waktu ke dalam blok:

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

Anda menambahkan enum privat untuk mengonversi setiap rentang waktu menjadi nilai diskret. Kemudian, metode GetTimeBand ini menggunakan pola relasional dan pola logis. Pola relasional mengizinkan Anda menguji nilai numerik menggunakan <, >, <=, atau >=. Pola logis menggabungkan pola lain: pola or menguji apakah ekspresi cocok dengan satu atau beberapa pola, dan pola and menguji bahwa ekspresi cocok dengan dua pola yang berbeda, dan pola not menguji bahwa ekspresi tidak cocok dengan suatu pola.

Setelah membuat metode tersebut, Anda dapat menggunakan ekspresi lain switch dengan pola tuple — pola posisi yang cocok dengan setiap elemen tuple — untuk menghitung biaya tambahan harga. Anda dapat membangun ekspresi switch dengan semua 16 lengan:

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

Kode sebelumnya berfungsi, tetapi dapat disederhanakan. Kedelapan kombinasi untuk akhir pekan memiliki biaya yang sama. Anda dapat mengganti semua delapan dengan baris berikut:

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

Lalu lintas masuk dan keluar memiliki pengali yang sama selama jam-jam siang hari dan jam-jam larut malam hari kerja. Anda dapat mengganti keempat cabang switch tersebut dengan dua baris berikut:

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

Kode akan terlihat seperti kode berikut setelah dua perubahan tersebut:

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

Terakhir, hapus dua waktu jam sibuk yang dikenai harga reguler. Setelah Anda melepas lengan tersebut, ganti false dengan discard (_) di lengan sakelar akhir. Anda mendapatkan metode yang sudah selesai berikut:

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

Contoh ini menyoroti salah satu keuntungan dari pencocokan pola: cabang pola dievaluasi secara berurutan. Jika Anda menyusun ulang cabang-cabang sehingga cabang sebelumnya menangani salah satu kasus Anda yang lebih kemudian, kompilator memperingatkan Anda tentang kode yang tidak dapat diakses. Aturan bahasa tersebut membuatnya lebih mudah untuk melakukan penyederhanaan sebelumnya dengan keyakinan bahwa kode tidak berubah.

Pencocokan pola membuat beberapa jenis kode lebih mudah dibaca dan menawarkan alternatif untuk teknik berorientasi objek ketika Anda tidak dapat menambahkan kode ke kelas Anda. Cloud menyebabkan data dan fungsionalitas menjadi terpisah. Bentuk data dan operasi di dalamnya tidak selalu dijelaskan bersama-sama. Dalam tutorial ini, Anda mengkonsumsi data yang ada dengan cara yang sama sekali berbeda dari fungsi aslinya. Pencocokan pola memberi Anda kemampuan untuk menulis fungsionalitas yang mengesampingkan jenis-jenis itu, meskipun Anda tidak dapat memperluasnya.

Langkah berikutnya

Anda dapat mengunduh kode jadi dari repositori GitHub dotnet/sampels. Jelajahi pola milik Anda sendiri dan tambahkan teknik ini ke dalam aktivitas pengkodean reguler Anda. Pembelajaran teknik ini memberi Anda cara lain untuk mendekati masalah dan membuat fungsionalitas baru.

Baca juga