C# อนุญาตให้ใช้ Multiple Deconstructor Methods ในโปรแกรมเดียวกัน ด้วยจำนวน Out Parameters เท่ากัน หรือ จำนวนและ Type ของ Out Parameters เท่ากันแต่ลำดับต่างกัน
มันเป็นส่วนหนึ่งของ Tuple Syntax ใหม่ - ไม่เกี่ยวกับ Tuple Classes แต่มาจาก Functional Programming
Keyword Deconstruct ใช้สำหรับ Deconstructors
ตัวอย่างพื้นฐาน
public class Employee {
public Employee(string employeeName, string firstName, string lastName) {
EmployeeName = employeeName;
FirstName = firstName;
LastName = lastName;
}
public string EmployeeName { get; }
public string FirstName { get; }
public string LastName { get; }
// Deconstructor
public void Deconstruct(out string employeeName, out string firstName, out string lastName) {
employeeName = EmployeeName;
firstName = FirstName;
lastName = LastName;
}
}
class Program {
public static void Main() {
Employee employee = new Employee("emp", "fname", "lname");
// Deconstruction Assignment
(string eName, string fName, string lName) = employee;
Console.WriteLine(eName); // emp
Console.WriteLine(fName); // fname
Console.WriteLine(lName); // lname
Console.ReadLine();
}
}
Output
emp
fname
lname
Multiple Deconstructors (Overloading)
public class Point {
public int X { get; }
public int Y { get; }
public int Z { get; }
public Point(int x, int y, int z = 0) {
X = x; Y = y; Z = z;
}
// Deconstruct 2D
public void Deconstruct(out int x, out int y) {
x = X; y = Y;
}
// Deconstruct 3D
public void Deconstruct(out int x, out int y, out int z) {
x = X; y = Y; z = Z;
}
}
// Usage
var p1 = new Point(1, 2);
var (x1, y1) = p1; // ใช้ Deconstruct 2D
var p2 = new Point(1, 2, 3);
var (x2, y2, z2) = p2; // ใช้ Deconstruct 3D
Deconstruction กับ Tuples
// Tuple Deconstruction (Built-in)
(string first, string last) = ("John", "Doe");
var (city, country) = ("Bangkok", "Thailand");
// Discard (_) สำหรับค่าที่ไม่ต้องการ
var (name, _, age) = GetPerson(); // Ignore middle value
Deconstruction ใน Foreach (C# 7.0+)
var people = new[] {
new Person("John", 25),
new Person("Jane", 30)
};
foreach (var (name, age) in people) {
Console.WriteLine($"{name} is {age} years old");
}
// กับ Dictionary
var dict = new Dictionary { ["a"] = 1, ["b"] = 2 };
foreach (var (key, value) in dict) {
Console.WriteLine($"{key} = {value}");
}
Extension Deconstructors (สำหรับ Types ที่แก้ไม่ได้)
// สำหรับ System.Drawing.Point (Sealed, ไม่มี Deconstruct)
public static class PointExtensions {
public static void Deconstruct(this Point p, out int x, out int y) {
x = p.X; y = p.Y;
}
}
// Usage
Point p = new Point(10, 20);
var (x, y) = p; // ใช้ Extension Deconstruct
Positional Records (C# 9.0+) - Auto Deconstruct
// Record Auto-generates Deconstructor
public record Person(string FirstName, string LastName, int Age);
// Usage
var person = new Person("John", "Doe", 30);
var (first, last, age) = person; // Auto Deconstruct
// หรือ
var (first, last, _) = person; // Discard Age
เมื่อไหร่ควร Implement Deconstruct
- Value-like Types (Data Containers, DTOs, Records)
- Types ที่มี Fields/Properties จำนวนน้อย (2-5)
- เมื่อ Client Code จะ Destructuring บ่อย
- Tuple-like Semantics
ข้อควรระวัง
- Deconstructor ต้องเป็น Instance Method (ไม่ใช่ Static)
- Parameters ต้องเป็น
outทั้งหมด - ชื่อ Method ต้องเป็น
Deconstructอย่างแน่นอน - Multiple Deconstructors ต้องมี Signature ต่างกัน (จำนวน/Type Parameters)
- ไม่ใช่ Destructor (
~ClassName()) - นั่เป็น Finalizer