Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

เมื่อไหร่ควรใช้ Tuple ใน C#

Tuple คืออะไร?

โครงสร้างข้อมูลที่จัดกลุ่มหลายค่า (Multiple Values) ไว้ใน Object เดียว โดยไม่ต้องสร้าง Class/Struct

  • Return หลายค่าจาก Method (แทน ref/out)
  • Pass หลายค่าเข้ Method ผ่าน Parameter เดียว
  • Nesting ได้ (Tuple ใน Tuple)
  • C# 7+: ValueTuple (Struct) - Performance ดีกว่า Tuple Class เดิม

Syntax แบบใหม่ (C# 7+ ValueTuple)


// Declaration with Names (Recommended)
(string Name, int Age, bool IsActive) person = ("John", 30, true);

// Access by Name
Console.WriteLine(person.Name);  // John
Console.WriteLine(person.Age);   // 30

// Access by Index (Item1, Item2...) - Backward Compatible
Console.WriteLine(person.Item1); // John

Use Case 1: Return Multiple Values


// แบบเก่า: out parameters, custom class, Tuple<T1,T2>
// แบบใหม่: ValueTuple - Clean Syntax
public (int Sum, int Count, double Average) CalculateStats(int[] numbers)
{
    if (numbers.Length == 0) return (0, 0, 0.0);
    
    int sum = numbers.Sum();
    int count = numbers.Length;
    double avg = (double)sum / count;
    
    return (sum, count, avg);
}

// เรียกใช้
var (sum, count, avg) = CalculateStats(new[] { 1, 2, 3, 4, 5 });
Console.WriteLine($"Sum: {sum}, Count: {count}, Avg: {avg}");
// Output: Sum: 15, Count: 5, Avg: 3

Use Case 2: Pass Multiple Values as Single Parameter


public void DisplayUser((string FirstName, string LastName, int Age) user)
{
    Console.WriteLine($"{user.FirstName} {user.LastName}, Age: {user.Age}");
}

// เรียกใช้
DisplayUser(("John", "Doe", 30));
// หรือ
var user = (FirstName: "Jane", LastName: "Smith", Age: 25);
DisplayUser(user);

Use Case 3: Deconstruction (แยกค่าออกมา)


var person = (Name: "Alice", Age: 28, City: "Bangkok");

// Full Deconstruction
var (name, age, city) = person;

// Partial Deconstruction (Discard _)
var (name, _, city) = person; // Age ถูก Discard

// Existing Variables
string name; int age;
(name, age, _) = person;

Use Case 4: Dictionary/Collection Operations


// Dictionary Deconstruction (C# 7+)
var dict = new Dictionary<string, int> { { "A", 1 }, { "B", 2 } };

foreach (var (key, value) in dict)
{
    Console.WriteLine($"{key} = {value}");
}

// LINQ with Tuples
var results = data
    .GroupBy(x => x.Category)
    .Select(g => (Category: g.Key, Count: g.Count(), Items: g.ToList()));

Tuple vs Anonymous Type vs Class/Record

FeatureTuple (ValueTuple)Anonymous TypeRecord (C# 9+)
Named Members✅✅✅
Return from Method✅❌ (object)✅
Pass as Parameter✅❌ (object)✅
Equality (Value-based)✅✅✅
Immutability❌ (Mutable Struct)✅✅ (init)
Methods/Behavior❌❌✅
SerializationLimitedLimitedFull Support

เมื่อไหร่ควรใช้ Tuple?

  • ✅ Return 2-4 ค่าที่เกี่ยวข้องกันชั่วคราว (Internal/Private Methods)
  • ✅ LINQ Projections, GroupBy Results
  • ✅ Deconstruction Patterns
  • ✅ Throwaway Data, Temporary Grouping

เมื่อไหร่ ไม่ควร ใช้?

  • ❌ Public API / Library Boundary (ใช้ Record/Class)
  • ❌ Complex Domain Objects (มี Behavior, Validation)
  • ❌ Long-lived Data (Mutable Struct ปัญหา Copy Semantics)
  • ❌ Serialization/DTO (ใช้ Record/Class + JSON Attributes)