Tuple là cấu trúc dữ liệu lightweight nhóm nhiều giá trị khác kiểu vào một đối tượng duy nhất. Từ C# 7.0 có ValueTuple (struct) với cú pháp SugarSyntax tốt hơn Tuple class (reference type) cũ.
1. Tuple Class (C# 4.0 - Legacy)
// Cú pháp cũ - Reference type, heap allocation Tuple<int, string> person = new Tuple<int, string>(32, "Steve"); Console.WriteLine(person.Item1); // 32 Console.WriteLine(person.Item2); // Steve // Tối đa 8 phần tử (Tuple<T1..T7, TRest>) var tuple8 = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9));
2. ValueTuple (C# 7.0+ - Khuyên dùng)
Struct, stack-allocated, có tên thành phần, deconstruction, so sánh giá trị.
Cú pháp tạo
// Cú pháp tường minh (int Age, string Name) person = (32, "Steve"); // Type inference (var) var person2 = (Age: 25, Name: "Alice", Active: true); // Tuple literal var point = (X: 10, Y: 20);
Truy cập thành phần
Console.WriteLine(person.Age); // 32 (tên) Console.WriteLine(person.Item1); // 32 (tên tự động Item1, Item2...) Console.WriteLine(person2.Name); // Alice Console.WriteLine(person2.Item3); // True
Deconstruction (Phân rã)
var (age, name) = person; // age=32, name="Steve"
var (_, nameOnly) = person; // Bỏ qua age với discard _
// Deconstruction trong foreach
var points = new[] { (1, 2), (3, 4), (5, 6) };
foreach (var (x, y) in points)
Console.WriteLine($"({x}, {y})");
So sánh và Equality
var t1 = (1, "a"); var t2 = (1, "a"); var t3 = (2, "b"); Console.WriteLine(t1 == t2); // True (structural equality) Console.WriteLine(t1.Equals(t2)); // True Console.WriteLine(t1.GetHashCode() == t2.GetHashCode()); // True
Ví dụ thực tế: Return multiple values từ method
using System;
class Program
{
// Trả về tuple có tên
static (int Sum, int Count, double Average) GetStats(int[] numbers)
{
if (numbers.Length == 0) return (0, 0, 0.0);
int sum = 0;
foreach (var n in numbers) sum += n;
return (sum, numbers.Length, (double)sum / numbers.Length);
}
static void Main()
{
var stats = GetStats(new[] { 10, 20, 30, 40, 50 });
Console.WriteLine($"Sum: {stats.Sum}, Count: {stats.Count}, Avg: {stats.Average}");
// Deconstruction
var (sum, count, avg) = GetStats(new[] { 1, 2, 3 });
Console.WriteLine($"{sum}, {count}, {avg}");
}
}
Kết quả
Sum: 150, Count: 5, Avg: 30 6, 3, 2
So sánh Tuple Class vs ValueTuple
| Đặc điểm | Tuple<...> (Class) | ValueTuple (Struct) |
|---|---|---|
| Kiểu | Reference type | Value type (struct) |
| Allocation | Heap | Stack (thường) |
| Tên thành phần | Không (Item1, Item2...) | Có (tên tùy chỉnh) |
| Deconstruction | Không | Có |
| Equality | Reference | Structural (giá trị) |
| Mutable | Immutable | Mutable (có thể gán lại) |
| Performance | Chậm hơn (GC) | Nhanh hơn |
Khuyến nghị: Luôn dùng ValueTuple (C# 7+) cho code mới. Chỉ gặp Tuple class trong legacy code.