ข้อเสนออย่างเป็นทางการของ Type Unions ใน C#
(github.com/dotnet)สรุป
เอกสารนี้เป็นข้อเสนอเกี่ยวกับ type unions (หรือ discriminated unions) ใน C#
แรงจูงใจ
- ในการพัฒนาซอฟต์แวร์ ค่าที่เก็บในตัวแปรอาจไม่ได้เป็นชนิดเดียวกันเสมอไป
- ตัวอย่างเช่น เมื่อคำจำกัดความของลูกค้าและซัพพลายเออร์มีการแชร์คุณสมบัติบางส่วนร่วมกัน อาจจำเป็นต้องทำงานที่คล้ายกันกับทั้งสองประเภท
- แม้จะแก้ปัญหาด้วยการสืบทอดได้ แต่ก็ไม่ได้เหมาะกับทุกสถานการณ์
- C# จำเป็นต้องมีวิธีเก็บชนิดที่แตกต่างกันจำนวนจำกัดไว้ในตัวแปรเดียวกันได้
- ภาษาอื่น ๆ มีความสามารถลักษณะนี้อยู่แล้ว
แนวทางแก้ไข
- วิธีที่เหมาะสมที่สุดในการทำให้ union types ใช้งานได้ใน C# อาจมองได้ว่าเป็นโครงสร้างลำดับชั้นที่ใช้ abstract base class
- อย่างไรก็ตาม ยังมีปัญหาเช่นข้อจำกัดของโครงสร้างลำดับชั้น และการไม่สามารถแสดงยูเนียนของชนิดที่ไม่เกี่ยวข้องกันได้
- อาจต้องการยูเนียนหลายรูปแบบ และข้อเสนอนี้แบ่งออกเป็น 4 หมวดหมู่
มาตรฐาน - union class
การประกาศ
- union class ถูกประกาศในลักษณะคล้าย
enum - แต่ละสมาชิกสามารถมี state variables ได้
การสร้าง
- สร้างโดยกำหนดอินสแตนซ์ของชนิดสมาชิก
การแยกโครงสร้าง
- แยกโครงสร้างด้วย type tests และ pattern matching
ความครอบคลุม
- หากพิจารณาชนิดสมาชิกทั้งหมดใน switch expression หรือ statement ก็ไม่จำเป็นต้องมีเคสเริ่มต้น
Nullability
- สามารถรวม
nullได้โดยใช้สัญกรณ์ nullability มาตรฐาน
การใช้งานจริง
- union class ถูก implement เป็น abstract record class
แบบเฉพาะทาง - union struct
การประกาศ
- ประกาศคล้าย union class แต่เพิ่มคีย์เวิร์ด
struct
การสร้าง
- สร้างโดยกำหนดอินสแตนซ์ของชนิดสมาชิก
การแยกโครงสร้าง
- แยกโครงสร้างด้วย type tests และ pattern matching
ความครอบคลุม
- หากพิจารณาชนิดสมาชิกทั้งหมดใน switch expression หรือ statement ก็ไม่จำเป็นต้องมีเคสเริ่มต้น
Nullability
- สามารถรวม
nullได้โดยใช้สัญกรณ์ nullability มาตรฐาน
ค่าเริ่มต้น
- union struct อาจอยู่ในสถานะที่ไม่ได้กำหนดเมื่อยังไม่ถูกกำหนดค่า หรือถูกกำหนดเป็นค่าเริ่มต้น
การใช้งานจริง
- union struct ถูก implement เป็น struct และชนิดสมาชิกถูก implement เป็น nested record struct
แบบชั่วคราว - ad hoc union
ไวยากรณ์
- ad hoc union ถูกอ้างอิงโดยใช้ไวยากรณ์แพตเทิร์น
or
การตั้งชื่อ
- สามารถตั้งชื่อร่วมให้กับ ad hoc union ได้ด้วย file หรือ global using alias
การสร้าง
- สร้างโดยกำหนดอินสแตนซ์ของชนิดสมาชิก
การแยกโครงสร้าง
- แยกโครงสร้างด้วย type tests และ pattern matching
ความครอบคลุม
- หากพิจารณาชนิดสมาชิกทั้งหมดใน switch expression หรือ statement ก็ไม่จำเป็นต้องมีเคสเริ่มต้น
Nullability
- สามารถรวม
nullได้โดยใช้สัญกรณ์ nullability มาตรฐาน
การใช้แทนกันได้
- ad hoc union ที่มีชนิดสมาชิกเหมือนกันสามารถใช้แทนกันได้
user-defined unions
- สามารถประกาศ union type ที่ไม่สามารถระบุเป็น union class หรือ union struct ได้
- สามารถปิดโครงสร้างลำดับชั้นได้ด้วยแอตทริบิวต์
Closed - สามารถ implement เป็น struct wrapper ได้ด้วยแอตทริบิวต์
Union
common unions
Option
- เป็น struct union ที่แทนค่าที่อาจมีอยู่หรือไม่มีอยู่ก็ได้
Result
- เป็น struct union สำหรับคืนผลลัพธ์ที่สำเร็จหรือข้อผิดพลาดจากฟังก์ชัน
ข้อเสนอที่เกี่ยวข้อง
โครงสร้างลำดับชั้นแบบปิด
- ประกาศชุดของ subtype แบบปิดสำหรับ abstract base type โดยใช้แอตทริบิวต์
Closed
ค่า singleton
- ชนิดที่มีแอตทริบิวต์ singleton สามารถใช้เป็นค่าได้ในบริบทที่ไม่ใช่ชนิด
การย่อสมาชิกที่ซ้อนกัน
- สามารถ bind ไปยัง static member หรือ nested type ของ target type ได้โดยใช้ชื่อที่ไม่ bind ไว้ล่วงหน้า
สรุปโดย GN⁺
- เอกสารนี้เสนอ type unions สำหรับ C# และมอบวิธีเก็บหลายชนิดไว้ในตัวแปรเดียวกันสำหรับสถานการณ์ที่หลากหลาย
- เป็นความพยายามนำความสามารถที่ภาษาอื่นมีอยู่แล้วเข้ามาใน C#
- อาจช่วยให้นักพัฒนายกระดับความอ่านง่ายและการบำรุงรักษาของโค้ดได้
- ตัวอย่างของภาษาอื่นที่มีความสามารถคล้ายกันคือ F#
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เคยใช้ discriminated unions ใน F# มาก่อน และคิดว่าน่าจะมีใน C# ด้วย
คำว่า "type unions" ฟังดูไม่คุ้นเคย
ในฐานะนักพัฒนา C# มานาน รู้สึกว่ายังไม่เห็น use case ของข้อเสนอนี้ชัดเจน
TypeScript มี type unions อยู่แล้ว
หากไม่มียูเนียนที่ทำ pattern matching ได้ การเขียนโปรแกรมจะยากขึ้น
เคยมีประสบการณ์ใช้ field offsets ใน C# unions
ใช้ private constructors และแพ็กเกจ nuget เพื่อให้ switch types ไม่ต้องมีเคส
_ไม่มีการกล่าวถึงว่า union structs จะจัดการกับ tearing อย่างไรเมื่อมีการแก้ไขพร้อมกัน