4 วิธีหลักในการ Return Multiple Values
| วิธี | เหมาะสำหรับ | ข้อดี | ข้อเสีย |
| Tuple (ValueTuple) | General Purpose, 2-7 Values | Clean Syntax, Named Members, Deconstruction | Mutable Struct, Limited Serialization |
| out Parameters | TryParse Pattern, Legacy | Clear Intent, No Allocation | Verbose, Must Initialize |
| ref Parameters | Modify Existing Variable | In/Out, Performance | Confusing, Side Effects |
| Class/Record/Struct | Complex Data, Public API, DTO | Type Safety, Behavior, Serialization | Boilerplate Code |
| Array/Collection | Variable Count, Same Type | Flexible Count | No Named Access, Boxing (Array) |
1. Tuple (แนะนำสำหรับ General Use)
// Named Tuple Return (C# 7+)
public (int Sum, int Count, double Average) GetStats(int[] numbers)
{
if (numbers.Length == 0) return (0, 0, 0.0);
return (numbers.Sum(), numbers.Length, numbers.Average());
}
// Deconstruction
var (sum, count, avg) = GetStats(new[] { 1, 2, 3 });
Console.WriteLine($"{sum}, {count}, {avg}"); // 6, 3, 2
2. out Parameters (Try Pattern)
// Standard Try Pattern
public bool TryParse(string input, out int result)
{
return int.TryParse(input, out result);
}
// Multiple out
public void GetCoordinates(out int x, out int y)
{
x = 10; y = 20;
}
// Usage
if (TryParse("123", out int value))
Console.WriteLine(value);
GetCoordinates(out int x, out int y);
3. ref Parameters (Modify Caller's Variable)
public void Increment(ref int value)
{
value++;
}
int num = 5;
Increment(ref num);
Console.WriteLine(num); // 6
// ref return (C# 7+) - Return Reference
public ref int FindElement(int[] arr, int value)
{
for (int i = 0; i < arr.Length; i++)
if (arr[i] == value) return ref arr[i];
throw new IndexOutOfRangeException();
}
4. Record / Class (Public API, Complex Data)
// Record (C# 9+) - Immutable, Value Equality, With Expression
public record UserResult(string Name, int Age, string Email, bool IsValid);
// Class - Mutable, Reference Equality
public class UserResult
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public bool IsValid { get; set; }
}
// Usage
public UserResult GetUser(int id)
{
return new UserResult("John", 30, "john@email.com", true);
}
5. Array / List (Variable Count, Same Type)
public int[] GetEvenNumbers(int max)
{
return Enumerable.Range(0, max).Where(x => x % 2 == 0).ToArray();
}
public List<string> GetNames()
{
return new List<string> { "A", "B", "C" };
}
Decision Guide
ต้อง Return กี่ค่า?
├── 2-7 ค่า ชนิดต่างกัน → Tuple (ValueTuple)
├── 1 ค่า + Success/Fail → out Parameter (Try Pattern)
├── Modify Existing Variable → ref Parameter
├── Complex Domain Object → Record/Class
├── Variable Count, Same Type → Array/List
└── Public API / Serialization → Record/Class
Best Practices
- ✅ ใช้ Tuple สำหรับ Internal/Private Methods
- ✅ ใช้ Record สำหรับ Public API, DTO, Serialization
- ✅ ใช้
out สำหรับ Try Pattern (TryParse, TryGetValue)
- ❌ หลีกเลี่ยง
ref เว้นแต่ Performance Critical
- ❌ อย่า Return Array/List ที่ Mutable ให้ External Modify ได้