Tuple dan dekonstruksi

Petunjuk / Saran

Baru mengembangkan perangkat lunak? Mulailah dengan tutorial Memulai . Anda akan menemukan tuple saat perlu mengembalikan beberapa nilai dari metode atau mengelompokkan nilai tanpa menentukan tipe yang diberi nama.

Berpengalaman dalam bahasa lain? Tuple C# adalah jenis nilai yang mirip dengan tuple di Python atau Swift, tetapi dengan elemen bernama opsional dan dukungan dekonstruksi penuh. Lewati bagian dekonstruksi dan kesetaraan untuk pola C#-spesifik.

Tuple mengelompokkan beberapa nilai ke dalam struktur tunggal yang ringan tanpa mengharuskan Anda menentukan jenis bernama. Tuples adalah jenis nilai yang dapat Anda deklarasikan sebaris, dikembalikan oleh metode, dan didekonstruksi menjadi variabel individual. Gunakan tuple saat Anda memerlukan pengelompokan cepat dan sementara dari nilai-nilai yang saling terkait. Misalnya, saat Anda mengembalikan beberapa hasil dari metode atau menyimpan pasangan koordinat.

Contoh berikut membuat tuple dengan elemen bernama dan mengakses setiap elemen berdasarkan nama:

var location = (Latitude: 47.6062, Longitude: -122.3321);
Console.WriteLine($"Location: {location.Latitude}, {location.Longitude}");
// Output: Location: 47.6062, -122.3321

Tuple bekerja dengan baik untuk pengelompokan yang berumur pendek, di mana mendefinisikan kelas, struktur, atau catatan akan menambah kerumitan yang tidak perlu. Untuk konsep atau jenis domain berumur panjang dengan perilaku, pilih rekaman, kelas, atau struktur. Untuk perbandingan kapan menggunakan masing-masing, lihat Memilih jenis jenis mana.

Mendeklarasikan dan menginisialisasi tuple

Deklarasikan tuple dengan mencantumkan jenis elemen dalam tanda kurung. Anda dapat secara opsional memberi nama setiap elemen untuk membuat kode lebih mudah dibaca:

// Tuple with named elements
(string Name, int Age) person = ("Alice", 30);
Console.WriteLine($"{person.Name} is {person.Age} years old");

// Tuple with default element names (Item1, Item2)
(string, int) unnamed = ("Bob", 25);
Console.WriteLine($"{unnamed.Item1} is {unnamed.Item2} years old");

// Tuple declared with var and inline names
var city = (Name: "Seattle", Population: 749_256);
Console.WriteLine($"{city.Name}: population {city.Population}");

Saat Anda tidak memberikan nama, elemen menggunakan nama Item1default , , Item2dan sebagainya. Elemen bernama membuat kode Anda mendokumen sendiri tanpa memerlukan definisi jenis terpisah.

Nama elemen yang disimpulkan

Pengkompilasi menyimpulkan nama elemen dari nama variabel atau nama properti yang Anda gunakan untuk menginisialisasi tuple. Fitur ini menghindari redundansi saat nama cocok:

var name = "Carol";
var age = 28;

// The compiler infers element names from the variable names
var person = (name, age);
Console.WriteLine($"{person.name} is {person.age}");
// Output: Carol is 28

Nama yang disimpulkan menyimpan ringkas kode Anda. Jika Anda memerlukan nama elemen yang berbeda, tentukan secara eksplisit.

Mengembalikan beberapa nilai dari metode

Salah satu kegunaan paling umum untuk tuple adalah mengembalikan beberapa nilai dari sebuah metode. Daripada menentukan kelas atau menggunakan parameter out, kembalikan tuple dengan elemen bernama:

static (double Minimum, double Maximum, double Average) ComputeStats(List<double> values)
{
    var min = values.Min();
    var max = values.Max();
    var avg = values.Average();
    return (min, max, avg);
}

Elemen tuple bernama membuat nilai pengembalian dapat dibaca baik di lokasi pemanggilan maupun dalam tanda tangan fungsi. Pemanggil dapat mengakses setiap nilai berdasarkan nama tanpa perlu mengingat urutan posisi.

Membongkar tuple

Dekonstruksi membongkar elemen tuple ke dalam variabel terpisah dalam satu pernyataan. Anda dapat mendekonstruksi tuple dengan beberapa cara:

var point = (X: 3, Y: 7);

// Deconstruct with var (infer all types)
var (x, y) = point;
Console.WriteLine($"x={x}, y={y}");

// Deconstruct with explicit types
(int px, int py) = point;
Console.WriteLine($"px={px}, py={py}");

// Deconstruct into existing variables
int a, b;
(a, b) = point;
Console.WriteLine($"a={a}, b={b}");

// Deconstruct a method return value directly
List<double> data = [10.0, 20.0, 30.0];
var (min, max, avg) = ComputeStats(data);
Console.WriteLine($"Min: {min}, Max: {max}, Avg: {avg}");

Dekonstruksi sangat berguna ketika Anda menerima tuple dari panggilan metode dan segera perlu bekerja dengan nilai individualnya.

Anda dapat mendekonstruksi tupel secara langsung dalam perulangan foreach, yang membuat iterasi atas koleksi nilai yang dikelompokkan menjadi ringkas.

List<(string Name, int Score)> results =
[
    ("Alice", 92),
    ("Bob", 87),
    ("Carol", 95)
];

foreach (var (name, score) in results)
{
    Console.WriteLine($"{name}: {score}");
}

Saat Anda tidak memerlukan setiap elemen, gunakan buang (_) sebagai pengganti setiap nilai yang ingin Anda abaikan. Gunakan _ yang terpisah untuk setiap posisi yang dibuang.

List<double> values = [5.0, 10.0, 15.0];
var (_, max, _) = ComputeStats(values);
Console.WriteLine($"Only need the max: {max}");
// Output: Only need the max: 15

Untuk informasi selengkapnya tentang menggunakan diskard di berbagai konteks, lihat Diskard.

Kesetaraan tuple

Anda dapat membandingkan tuple menggunakan == dan !=. Operator ini membandingkan elemen-elemen secara berurutan, artinya dua tuple dianggap setara ketika semua elemen yang bersesuaian juga setara.

var order1 = (Product: "Widget", Quantity: 5);
var order2 = (Product: "Widget", Quantity: 5);
var order3 = (Product: "Gadget", Quantity: 3);

Console.WriteLine(order1 == order2); // True
Console.WriteLine(order1 == order3); // False

// Element names don't affect equality—only values matter
var named = (X: 1, Y: 2);
var different = (A: 1, B: 2);
Console.WriteLine(named == different); // True

Kesetaraan == tuple menggunakan operator yang diimplementasikan pada setiap jenis elemen, yang berarti pembandingan berfungsi dengan benar untuk string, angka, dan jenis lain yang menentukan ==. Nama elemen tidak memengaruhi kesetaraan—hanya nilai dan posisi yang penting.

Mutasi nondestruktif dengan with

Ekspresi with membuat salinan tuple dengan satu atau beberapa elemen berubah, membiarkan aslinya tidak berubah:

var original = (Name: "Widget", Price: 19.99m, InStock: true);
var discounted = original with { Price = 14.99m };

Console.WriteLine($"Original: {original.Name} at {original.Price:C}");
Console.WriteLine($"Discounted: {discounted.Name} at {discounted.Price:C}");
// Output:
// Original: Widget at $19.99
// Discounted: Widget at $14.99

Pola ini berguna ketika Anda menginginkan variasi tuple yang ada tanpa memodifikasi yang asli. Ekspresi with bekerja dengan cara yang sama pada tuple seperti pada record.

Tuple dalam kamus dan pencarian

Tuple membuat nilai kamus yang nyaman ketika Anda perlu mengaitkan kunci dengan beberapa bagian data:

var sizeChart = new Dictionary<string, (int Min, int Max)>
{
    ["Small"] = (0, 50),
    ["Medium"] = (51, 100),
    ["Large"] = (101, 200)
};

if (sizeChart.TryGetValue("Medium", out var range))
{
    Console.WriteLine($"Medium: {range.Min}–{range.Max}");
}
// Output: Medium: 51–100

Tuple juga berfungsi sebagai kunci kamus, memberi Anda kunci komposit tanpa menentukan jenis kustom. Karena tuple mengimplementasikan kesetaraan struktural, pencarian cocok pada nilai gabungan dari semua elemen:

var grid = new Dictionary<(int Row, int Column), string>
{
    [(0, 0)] = "Origin",
    [(1, 3)] = "Sensor A",
    [(2, 5)] = "Sensor B"
};

var target = (Row: 1, Column: 3);
if (grid.TryGetValue(target, out var label))
{
    Console.WriteLine($"({target.Row}, {target.Column}): {label}");
}
// Output: (1, 3): Sensor A

Pola ini menghindari perlunya kelas terpisah untuk pencarian multi-kunci sederhana atau pemetaan kunci-ke-beberapa nilai.

Tuple vs. jenis anonim

Tuple adalah pilihan yang disukai ketika Anda membutuhkan struktur data ringan tanpa nama. Jenis anonim tetap tersedia untuk skenario pohon ekspresi dan untuk kode yang memerlukan jenis referensi, tetapi tuple menawarkan performa yang lebih baik, dukungan dekonstruksi, dan sintaks yang lebih fleksibel. Untuk informasi selengkapnya tentang jenis anonim, lihat Memilih antara jenis anonim dan tuple.

Baca juga