Từ C# 7.0, ValueTuple (struct) cung cấp syntax sugar cho tuple, thay thế System.Tuple (class) cũ.
Tuple Literals (C# 7.0+)
// Named tuple elements (khuyến nghị)
var person = (Id: 1, Name: "John", Email: "john@example.com");
Console.WriteLine($"{person.Name} - {person.Email}"); // John - john@example.com
// Implicit naming từ biến
var id = 1; var name = "John";
var person2 = (id, name); // Elements tên là id, name
List của Tuple
// C# 7.0+ List
var people = new List<(int Id, string Name, string Email)>
{
(1, "Alice", "alice@test.com"),
(2, "Bob", "bob@test.com"),
(3, "Charlie", "charlie@test.com")
};
foreach (var p in people)
Console.WriteLine($"{p.Id}: {p.Name} <{p.Email}>");
Array của Tuple
var coordinates = new (double X, double Y)[]
{
(10.5, 20.3),
(15.2, 25.8),
(30.0, 40.1)
};
Nested Tuple (Tuple lồng nhau)
// C# 7.0+ hỗ trợ nested tuple tự nhiên
var data = (Id: 1, Name: "Product", Tags: ("tag1", "tag2", "tag3"));
Console.WriteLine(data.Tags.Item1); // tag1
// Hoặc dùng ValueTuple lồng
var complex = (1, "Test", (true, 3.14, "nested"));
Tuple làm Parameter & Return Type
// Parameter
static void PrintPerson((int Id, string Name, int Age) person)
{
Console.WriteLine($"{person.Name} ({person.Age})");
}
// Return tuple
static (bool Success, string Message, int Code) TryParse(string input)
{
if (int.TryParse(input, out int value))
return (true, "Parsed", value);
return (false, "Invalid number", 0);
}
// Deconstruction
var (success, msg, code) = TryParse("123");
if (success) Console.WriteLine($"{msg}: {code}");
Tuple vs System.Tuple (Class cũ)
| Đặc điểm | ValueTuple (struct) | Tuple<T> (class) |
|---|---|---|
| Syntax | (int, string), (Id, Name) | Tuple.Create(1, "a"), new Tuple<int,string>(1,"a") |
| Named elements | Có (compile-time) | Không (Item1, Item2...) |
| Performance | Struct, no heap allocation | Class, heap allocation |
| Mutability | Mutable (có thể gán lại field) | Immutable |
| Max elements | Không giới hạn | 8 (Tuple<T1..T8>) |
| Serialization | Cần custom (JSON.NET hỗ trợ) | Hỗ trợ sẵn |
Deconstruction (Phân rã tuple)
var (id, name, email) = people[0]; // Deconstruct
Console.WriteLine(name); // Alice
// Deconstruct vào biến có sẵn
int existingId;
(existingId, name, email) = people[1];
Discard (_) - Bỏ qua element không cần
var (_, name, _) = people[0]; // Chỉ lấy name
Console.WriteLine(name);