1 điểm bởi GN⁺ 2024-08-09 | 1 bình luận | Chia sẻ qua WhatsApp

Tóm tắt

Đây là tài liệu đề xuất type union (hoặc discriminated union) cho C#.

Động lực

  • Khi phát triển phần mềm, giá trị được lưu trong một biến không phải lúc nào cũng cùng một loại.
  • Ví dụ, khi định nghĩa khách hàng và nhà cung cấp chỉ chia sẻ một phần thuộc tính, có thể cần thực hiện các thao tác tương tự với cả hai kiểu.
  • Có thể giải quyết bằng kế thừa, nhưng không phù hợp với mọi tình huống.
  • C# cần một cách để lưu một số lượng hữu hạn các kiểu khác nhau trong cùng một biến.
  • Các ngôn ngữ khác đã cung cấp tính năng này.

Giải pháp

  • Cách phù hợp nhất để hiện thực union type trong C# có thể được xem là một hệ phân cấp dùng abstract base class.
  • Tuy nhiên, cách này có các vấn đề như ràng buộc của hệ phân cấp, hoặc không thể biểu diễn union của các kiểu không liên quan.
  • Có thể cần nhiều loại union khác nhau, và đề xuất này phân chúng thành bốn danh mục.

Tiêu chuẩn - Union class

Khai báo

  • Union class được khai báo tương tự như enum.
  • Mỗi member có thể có biến trạng thái.

Tạo

  • Được tạo bằng cách gán một instance của kiểu member.

Phân rã

  • Được phân rã thông qua kiểm tra kiểu và pattern matching.

Tính bao quát

  • Nếu mọi kiểu member đều được xét trong biểu thức hoặc câu lệnh switch, thì không cần case mặc định.

Khả năng null

  • Có thể bao gồm null bằng cách dùng ký hiệu khả năng null tiêu chuẩn.

Triển khai

  • Union class được triển khai dưới dạng abstract record class.

Chuyên biệt hóa - Union struct

Khai báo

  • Được khai báo tương tự union class, nhưng thêm từ khóa struct.

Tạo

  • Được tạo bằng cách gán một instance của kiểu member.

Phân rã

  • Được phân rã thông qua kiểm tra kiểu và pattern matching.

Tính bao quát

  • Nếu mọi kiểu member đều được xét trong biểu thức hoặc câu lệnh switch, thì không cần case mặc định.

Khả năng null

  • Có thể bao gồm null bằng cách dùng ký hiệu khả năng null tiêu chuẩn.

Giá trị mặc định

  • Union struct có thể ở trạng thái chưa xác định khi chưa được gán hoặc khi được gán giá trị mặc định.

Triển khai

  • Union struct được triển khai dưới dạng struct, còn các kiểu member được triển khai dưới dạng nested record struct.

Tạm thời - Union tạm thời

Cú pháp

  • Union tạm thời được tham chiếu bằng cú pháp pattern or.

Đặt tên

  • Có thể dùng file hoặc global using alias để gán một tên chung cho union tạm thời.

Tạo

  • Được tạo bằng cách gán một instance của kiểu member.

Phân rã

  • Được phân rã thông qua kiểm tra kiểu và pattern matching.

Tính bao quát

  • Nếu mọi kiểu member đều được xét trong biểu thức hoặc câu lệnh switch, thì không cần case mặc định.

Khả năng null

  • Có thể bao gồm null bằng cách dùng ký hiệu khả năng null tiêu chuẩn.

Tính thay thế cho nhau

  • Các union tạm thời có cùng các kiểu member thì có thể thay thế cho nhau.

Union do người dùng định nghĩa

  • Có thể khai báo các union type không thể biểu diễn bằng union class hoặc union struct.
  • Có thể đóng hệ phân cấp bằng thuộc tính Closed.
  • Có thể triển khai bằng struct wrapper với thuộc tính Union.

Union phổ biến

Option

  • Đây là một struct union biểu diễn một giá trị có thể tồn tại hoặc không tồn tại.

Result

  • Đây là một struct union dùng để trả về kết quả thành công hoặc lỗi từ hàm.

Các đề xuất liên quan

Hệ phân cấp đóng

  • Dùng thuộc tính Closed để khai báo một tập hợp kiểu con đóng cho abstract base type.

Giá trị singleton

  • Kiểu có thuộc tính singleton có thể được dùng như giá trị trong ngữ cảnh không phải kiểu.

Rút gọn member lồng nhau

  • Có thể dùng tên chưa được bind để bind tới static member hoặc nested type của target type.

Tóm tắt của GN⁺

  • Tài liệu này đề xuất type union cho C#, cung cấp cách lưu nhiều kiểu trong biến ở nhiều tình huống khác nhau.
  • Đây là nỗ lực đưa vào C# một tính năng mà các ngôn ngữ khác đã hỗ trợ.
  • Nó có thể giúp lập trình viên cải thiện độ dễ đọc và khả năng bảo trì của mã.
  • F# là một ví dụ về ngôn ngữ khác có tính năng tương tự.

1 bình luận

 
GN⁺ 2024-08-09
Ý kiến trên Hacker News
  • Đã từng dùng discriminated union trong F# và nghĩ rằng C# cũng phải có

    • Hiện đang dùng Java và cảm thấy rất khó quay lại một ngôn ngữ không có ADT
    • Vui vì không còn phải xin lỗi cho việc C# thiếu một tính năng quan trọng
  • Thuật ngữ "type union" nghe khá lạ

    • Có vẻ tương tự tagged union trong các ngôn ngữ họ ML
    • Tò mò không biết các lập trình viên C# có xu hướng đặt tên khác với thuật ngữ vốn có hay không
  • Với tư cách là một lập trình viên C# lâu năm, cảm thấy trường hợp sử dụng của đề xuất này chưa rõ ràng

    • Có vẻ có thể triển khai bằng cách khai báo interface rỗng và các record class
    • Tò mò không biết mình có đang bỏ sót điều gì không
  • TypeScript có type union

    • Có vẻ tương tự discriminated union trong F# hoặc Haskell
    • Discriminated union có các case constructor được đặt tên
  • Nếu không có union hỗ trợ pattern matching thì việc lập trình trở nên khó khăn

    • Chưa từng hiểu hoàn toàn ý nghĩa của expression problem
    • Các điểm mở rộng thông qua polymorphism hiện có có thể phù hợp với client trong tương lai
    • Với mã do đội ngũ sở hữu, union hỗ trợ pattern matching phù hợp hơn
  • Đã từng có kinh nghiệm với union trong C# dùng field offset

    • Việc alias giữa giá trị con trỏ/tham chiếu và giá trị thường có thể gây ra hành vi không xác định
    • Union struct giữa u64 và object có thể cần các field riêng biệt, làm lãng phí 8 byte
  • Dùng constructor riêng tư và gói nuget để kiểu switch không cần case _

    • Tương tự phiên bản desugar của "union class" được đề xuất
    • Thật tốt khi gói nuget trở nên không cần thiết và có thêm cú pháp đường
  • Không thấy đề cập union struct sẽ xử lý tearing thế nào khi bị sửa đổi đồng thời

    • Tearing có thể gây ra vấn đề an toàn bộ nhớ
    • Có thể tồn tại các biến thể có field số nguyên và field tham chiếu cùng nằm ở một offset