Tuple เป็นโครงสร้างข้อมูลที่เก็บค่าหลายค่า (Elements) ที่ชนิดข้อมูลต่างกันได้ จำกัดสูงสุด 8 Elements (ใน Tuple<T1..T8>) แต่ C# 7.0+ มี ValueTuple (Struct) ที่รองรับ Unlimited Elements และมี Syntax Sugar
Tuple แบบเก่า (Reference Type - System.Tuple)
// ต้องระบุ Type ทุกตัว
Tuple<int, string, string> person = new Tuple<int, string, string>(1, "John", "Doe");
// List ของ Tuple แบบเก่า
var oldTupleList = new List<Tuple<int, string>>
{
new Tuple<int, string>(1, "Cow"),
new Tuple<int, string>(5, "Chickens"),
new Tuple<int, string>(1, "Airplane")
};
ValueTuple แบบใหม่ (C# 7.0+ / .NET Framework 4.7+ / .NET Core)
Syntax: (Type1 Name1, Type2 Name2, ...) - Named Elements
1. Tuple List แบบ Inline (สะดวกที่สุด)
// Implicit Types (Target-typed new)
var tupleList = new List<(int Id, string Name)>
{
(1, "Cow"),
(5, "Chickens"),
(1, "Airplane")
};
// Explicit Types
List<(int Id, string Name)> explicitList = new()
{
(1, "Cow"),
(5, "Chickens"),
(1, "Airplane")
};
2. Tuple Array
var tupleArray = new (int Id, string Name)[]
{
(1, "Cow"),
(5, "Chickens"),
(1, "Airplane")
};
3. Nested Tuples
// Tuple ใน Tuple
var nested = (1, (2, 3), "Test");
Console.WriteLine(nested.Item2.Item1); // 2
// หรือ Named
var namedNested = (Id: 1, Coords: (X: 10, Y: 20), Label: "Point");
Console.WriteLine(namedNested.Coords.X); // 10
4. Tuple เป็น Parameter และ Return Type
// Parameter
static void PrintPerson((int Id, string FirstName, string LastName) person)
{
Console.WriteLine($"{person.Id}: {person.FirstName} {person.LastName}");
}
// Return
static (int Id, string Name, string Email) GetUser(int id)
{
return (id, "John Doe", "john@example.com");
}
// ใช้งาน
var user = GetUser(42);
Console.WriteLine($"{user.Name} ({user.Email})");
5. Deconstruction (แยกค่าออกมา)
var (id, name, email) = GetUser(1); // Deconstruct
Console.WriteLine(name); // John Doe
// ใน Loop
foreach (var (id, name) in tupleList)
{
Console.WriteLine($"{id}: {name}");
}
6. Discards (ข้ามค่าที่ไม่ต้องการ)
var (_, name, _) = GetUser(1); // รับแค่ Name
var (id, _, _) = GetUser(1); // รับแค่ Id
การเข้าถึงค่า
| Syntax | คำอธิบาย |
|---|---|
tuple.Item1, Item2... |
Default Names (Unnamed) |
tuple.Name |
Named Element (แนะนำ) |
tuple.GetType() |
ValueTuple<...> Struct |
ข้อดีของ ValueTuple vs Tuple
- Struct (Value Type) - No Heap Allocation, Better Performance
- Mutable (สามารถแก้ค่าได้)
- Named Elements - อ่านโค้ดเข้าใจง่าย
- Deconstruction - แยกตัวแปรได้ง่าย
- Equality: Structural (เปรียบเทียบค่าแต่ละ Field)
ข้อควรระวัง
- Struct: การส่งผ่าน Parameter เป็น By Value (Copy) - ใหญ่เกินไปอาจช้า
- Serialization: บาง Serializer ไม่รองรับ Named Tuple ได้ดี
- Public API: ควรใช้ Class/Record แทน Tuple สำหรับ Contract