Hướng dẫn nhanh và ví dụ về pattern matching trong C#

Với mỗi bản phát hành mới của C#, pattern matching (khớp mẫu) được cải tiến cho các nhà phát triển C#. Mặc dù các nhà phát triển ngày nay không sử dụng rộng rãi khớp mẫu, nhưng chúng ta có thể sẽ thấy việc áp dụng nó tăng lên khi nhiều nhóm và ứng dụng chuyển từ .NET Framework (.NET 4.8) sang các phiên bản mới hơn (.NET 5+)

Giống như hầu hết các tính năng độc đáo của ngôn ngữ, luôn có phản ứng đầu tiên là chấp nhận nó, sử dụng nó ở mọi nơi hoặc hoàn toàn ghét nó. Bất kể chúng ta thuộc loại nào, chúng ta cần hiểu một số trường hợp sử dụng hàng ngày trong trường hợp chúng ta muốn làm việc với khớp mẫu C#.

Bài viết này sẽ trình bày một số ví dụ về các kịch bản khớp mẫu mà tôi thấy hữu ích và bạn có thể muốn xem xét sử dụng trong các dự án hiện tại hoặc tương lai của bạn.

Các kiểu dữ liệu

Đối với hướng dẫn này, chúng ta sẽ sử dụng các kiểu record sau.

abstract record Food;
record Pizza(params string[] Toppings) : Food;
record Burger(int NumberOfPatties = 1, bool HasCheese = true): Food;
record Chicken(CookKind Kind = CookKind.Fried): Food;

enum CookKind
{
    Fried,
    Grilled,
    Baked
}

Kết hợp kiểm tra và khai báo kiểu

Một trong những cách sử dụng mới yêu thích của tôi cho khớp mẫu liên quan đến một từ khóa cũ là if và một từ khóa mới là is, được áp dụng theo một cách mới và thú vị. Chúng ta hãy xem một số ví dụ.

Food food = new Pizza("pepperoni");

// check and declare a variable of a specific type
if (food is Pizza pizza)
{
    Console.WriteLine($"this pizza has {string.Join(", ", pizza.Toppings)}");
}

Chúng ta có thể kiểm tra xem biến có đáp ứng điều kiện cho một kiểu hay không và khai báo một biến để chúng ta sử dụng trong phạm vi câu lệnh if. Nếu các nhà phát triển sử dụng bất kỳ khớp mẫu nào trong mã của họ, thì hãy để nó là mẫu này.

Kiểm tra rỗng

Nullability là một tính năng mới hơn của C#, hy vọng sẽ giúp giảm kiểm tra null trong toàn bộ codebase của chúng ta bằng cách cung cấp các đảm bảo an toàn với null.

Hầu hết các codebase vẫn chưa kích hoạt tính năng này, vì vậy nhiều người trong chúng ta vẫn phải dựa vào việc kiểm tra các giá trị null. Chúng ta sẽ sử dụng lại từ khóa is và xem cách chúng ta có thể kiểm tra xem biến là null hay không null.

// check the variable is null
if (food is null)
{
    Console.WriteLine("It's Null!");
}

// check that the variable is something
if (food is object)
{
    
}

// same as "is object"
// but uses the object pattern
if (food is { })
{
    Console.WriteLine("Not Null!");
}

Các nhà phát triển lần đầu tiên nhìn thấy điều này sẽ hỏi, tại sao điều này lại tốt hơn toán tử == hay !=? Nó không tốt hơn; nó chỉ là một cách tiếp cận khác với hy vọng làm cho mã dễ đọc hơn. Định nghĩa của con người có thể đọc được phụ thuộc vào chủ quan.

Tối ưu xử lý ngoại lệ

Kinh nghiệm đầu tiên của tôi với khớp mẫu là sử dụng từ khóa when để xử lý ngoại lệ Exception. Các thư viện kế thừa nổi tiếng với việc đưa ra các ngoại lệ chung với nhiều thông tin chi tiết hơn được tìm thấy trong InnerException hoặc trong thuộc tính Message.

// refined exception handling
try
{
    // super complex legacy library
    // that throws one type of exception
}
catch (Exception e) 
    when (e.Message.Contains("Ah!"))
{
    // handle that strange exception
}

Trong ví dụ này, chúng ta sẽ chỉ bắt được một Exception theo nội dung tin nhắn cụ thể. Mã sẽ ném các ngoại lệ khác, cho phép chúng ta xử lý chúng sau này trong codebase của chúng ta.

Câu lệnh switch

Câu lệnh switch nhận được giải thưởng được cải thiện nhiều nhất khi nói đến việc bổ sung khớp mẫu. Chúng ta không còn phải giải quyết các câu lệnh switch trên các kiểu nguyên thủy. Bây giờ chúng ta có thể sử dụng các đối tượng phức tạp với khả năng lồng nhiều câu lệnh switch hơn.

var healthy = food switch
{
    Pizza p => false,
    Burger b => false,
    // branching into a sub pattern matching
    Chicken c => c switch
    {
        { Kind: CookKind.Fried } => false,
        _ => true
    }, 
    _ => false
};

Đặc điểm cơ bản cần lưu ý trong đoạn mã này là .NET sẽ đánh giá từng phần trong câu lệnh switch của chúng ta theo thứ tự mà nó được xác định. Hãy tưởng tượng các câu lệnh switch này tương tự như chiếc xe bus sẽ dừng ở các điểm dừng trên tuyến, với biến loại bỏ _, là điểm dừng cuối cùng trên tuyến.

Chúng ta cũng có thể thấy ví dụ về khai báo kiểu cho Pizza, Burger Chicken. Trong câu lệnh switch ở Chicken, chúng ta sử dụng khớp mẫu đối tượng để xác định loại gà.

Khớp mẫu đối tượng

Với C# 9, các nhà phát triển đã nhận được mô hình kết hợp đối tượng và một số từ khóa mới như and or như một phần của khớp mẫu. Giải cấu trúc, một tính năng mặc định của kiểu record, thêm một khớp mẫu khác, như chúng ta sẽ thấy trong ví dụ ở bên dưới.

food = new Burger(3, true);
// terse if statements
if (food is Burger {NumberOfPatties: > 2, HasCheese: true})
{
    Console.WriteLine("Yum!");
}

// use the deconstruct method of
// our Burger record type to make for a
// terser if statment
if (food is Burger(> 2, true))
{
    Console.WriteLine("Yum!");
}

// filter by type and declare a variable
Food lunch = new Chicken(CookKind.Grilled);
if (food is Burger { NumberOfPatties: > 0 and < 3 } burger)
{
    Console.WriteLine($"{burger.NumberOfPatties} Patties For Me!");
}

if (lunch is Chicken {Kind: CookKind.Baked or CookKind.Grilled} chicken)
{
    Console.WriteLine("Eating Healthy!");
}

Những ví dụ này cho thấy từ khóa thích and or có thể giảm nhiễu các câu lệnh logic của chúng ta như thế nào. Chúng ta cũng thấy sự xuất hiện lại của khai báo biến bằng cách thêm tên biến vào cuối khớp mẫu đối tượng của chúng ta.

Phần kết luận

Khớp mẫu là một chủ đề gây tranh cãi trong cộng đồng .NET, một số cho rằng nó “không còn giống C# nữa”, một số cho rằng đó là các chức năng làm cho ngôn ngữ C# tốt hơn”.

Bất kể ý kiến ​​như thế nào, các tính năng này đã có sẵn trong C# 9 và bạn nên tìm hiểu cách khớp mẫu mới này. Có kỹ thuật hoặc cách tiếp cận nào với khớp mẫu mà tôi đã bỏ qua không?

Như mọi khi, cảm ơn bạn vì đã dành thời gian đọc bài viết này.

Nếu Comdy hữu ích và giúp bạn tiết kiệm thời gian làm việc

Bạn có thể vui lòng đưa Comdy vào whitelist của trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi trong việc trả tiền cho dịch vụ lưu trữ web để duy trì hoạt động của trang web.

Lập Trình C#
Bài Viết Liên Quan:
Tạo tập tin Zip với .NET 5
Trung Nguyen 11/11/2021
Tạo tập tin Zip với .NET 5

Trong bài viết này, chúng ta sẽ tìm hiểu lớp tiện ích ZipFile trong C#, cách nén tập tin và thư mục, cùng với giải nén tập tin zip.

Đọc và ghi file Excel trong C#
Trung Nguyen 29/10/2021
Đọc và ghi file Excel trong C#

Bài viết này sẽ giới thiệu cách đơn giản nhất mà tôi đã tìm thấy để đọc và ghi file Excel bằng C# sử dụng ExcelMapper.

Làm việc với PriorityQueue của .NET 6
Trung Nguyen 25/10/2021
Làm việc với PriorityQueue của .NET 6

Bài viết này sẽ giúp bạn tìm hiểu PriorityQueue của .NET 6 là gì, cách chúng ta thêm các phần tử và cách chúng ta có thể xếp hàng lại cho các phần tử.

Sử dụng chuỗi kết nối Redis-CLI trong StackExchange.Redis
Trung Nguyen 18/10/2021
Sử dụng chuỗi kết nối Redis-CLI trong StackExchange.Redis

Bài viết này sẽ hướng dẫn chúng ta cách viết một phương thức mở rộng để phân tích chuỗi kết nối redis-cli có thể sử dụng với thư viện StackExchange.Redis.