Mendekonstruksi tuple dan tipe lain

Tip

Artikel ini adalah bagian dari bagian Dasar-Dasar untuk pengembang yang sudah mengetahui setidaknya satu bahasa pemrograman dan mempelajari C#. Mulailah dengan gambaran umum pencocokan pola jika pola baru bagi Anda.

Dekonstruksi menugaskan bagian-bagian individual dari suatu nilai — komponennya — ke beberapa variabel dalam satu operasi. Komponen tuple adalah elemennya, diekspos berdasarkan posisi. Jenis lain dapat mengekspos komponen dengan mendefinisikan metode Deconstruct. Record posisional, yang mendeklarasikan propertinya sebagai parameter seperti konstruktor, mendapatkan metode Deconstruct secara otomatis.

Membongkar tuple

Misalkan metode mengembalikan tuple dengan data kota. Anda dapat membaca setiap komponen satu per satu:

var cityData = QueryCityData("New York City");
var city = cityData.City;
var population = cityData.Population;
var area = cityData.Area;

Dekonstruksi menguraikan komponen tersebut dalam satu langkah:

(string city, int population, double area) = QueryCityData("New York City");

Anda juga dapat membiarkan C# menyimpulkan jenis variabel:

var (city, population, area) = QueryCityData("New York City");

Dekonstruksi variabel dapat mencampur variabel yang ada, variabel yang baru dideklarasikan, dan placeholder yang diabaikan dalam satu penugasan:

(city, var population, _) = QueryCityData("New York City");

Pilih bentuk yang membuat kode paling mudah dibaca. Satu var sebelum tanda kurung sering kali merupakan bentuk yang disimpulkan paling jelas. Anda juga dapat mencampur jenis eksplisit dan var di dalam tanda kurung, tetapi bentuk tersebut biasanya lebih sulit dipindai. Jika Anda hanya memerlukan beberapa nilai, gunakan discards alih-alih menghilangkan posisi.

Abaikan nilai yang tidak diperlukan dengan discard

Setiap nilai yang dihasilkan harus sesuai dengan posisi di sisi kiri penugasan. Ketika Anda tidak memerlukan satu atau beberapa posisi, gunakan _ untuk mengabaikannya:

var (_, _, population1960, _, population2010) = QueryPopulationDataForYears(
    "New York City", 1960, 2010);

Di sini, tupel mengembalikan nama kota, dua tahun, dan dua nilai populasi. Dekonstruksi hanya menyimpan nilai populasi karena perhitungan hanya menggunakan komponen tersebut.

Uraikan tipe yang ditentukan pengguna

Kelas, struktur, atau antarmuka dapat mendukung dekonstruksi dengan mendeklarasikan metode Deconstruct. Setiap komponen menjadi out parameter, yang memungkinkan metode menetapkan nilai kembali ke variabel pemanggil tanpa mengembalikannya. Karena setiap komponen dikembalikan melalui parameter out, metode itu sendiri mengembalikan void:

public void Deconstruct(out string firstName, out string middleName, out string lastName)
{
    firstName = FirstName;
    middleName = MiddleName;
    lastName = LastName;
}

Anda kemudian dapat mendekonstruksi instans secara langsung:

var (firstName, middleName, lastName) = passenger;

Suatu tipe dapat menyediakan beberapa Deconstruct overload dengan aritas yang berbeda — jumlah out parameter yang dideklarasikan metode — sehingga pemanggil dapat memilih berapa banyak komponen yang akan diambil:

public void Deconstruct(out string firstName, out string lastName)
{
    firstName = FirstName;
    lastName = LastName;
}

public void Deconstruct(out string firstName, out string middleName, out string lastName)
{
    firstName = FirstName;
    middleName = MiddleName;
    lastName = LastName;
}

public void Deconstruct(out string firstName, out string lastName, out string city, out string state)
{
    firstName = FirstName;
    lastName = LastName;
    city = City;
    state = State;
}

Dua overload dengan jumlah parameter out yang sama ambigu. Kompilator melaporkan kesalahan untuk panggilan ambigu, jadi bedakan overload berdasarkan aritas, tidak hanya berdasarkan jenis parameter.

Discard juga berfungsi dengan dekonstruksi yang ditentukan pengguna. Untuk informasi selengkapnya tentang discards secara umum, lihat Discards dan pola discard:

var (firstName, _, city, _) = passenger;

Uraikan rekor

Sebuah posisional record atau record struct mendeklarasikan propertinya sebagai parameter pada deklarasi tipe itu sendiri, mirip dengan konstruktor. Pengkompilasi menghasilkan metode Deconstruct untuk Anda, dengan parameter out yang cocok dengan parameter posisi tersebut:

var (city, highTempC, lowTempC) = forecast;

Hanya parameter posisi yang berpartisipasi dalam deconstruction yang dihasilkan. Properti tambahan yang Anda deklarasikan di tempat lain pada rekor tidak ditambahkan secara otomatis.

Dekonstruksi tipe yang tidak Anda miliki

Jika Anda tidak dapat mengubah tipe, Anda masih dapat mendukung dekonstruksi dengan menulis metode ekstensi — metode statis yang menambahkan Deconstruct metode ke tipe yang tidak Anda miliki, seolah-olah itu adalah anggota dari tipe tersebut. Setelah Anda menambahkan metode, Uri nilai apa pun dapat menggunakan sintaks dekonstruksi:

static class UriExtensions
{
    public static void Deconstruct(this Uri uri, out string scheme, out string host, out int port)
    {
        scheme = uri.Scheme;
        host = uri.Host;
        port = uri.Port;
    }
}

Aturan ambiguitas yang sama berlaku di sini: dua metode ekstensi Deconstruct dengan aritas yang sama ambigu. Ambiguitas juga dapat muncul antara metode instans Deconstruct dan metode ekstensi dengan aritas yang sama. Dalam kedua kasus, pengompilasi melaporkan kesalahan untuk panggilan ambigu.

Dekonstruksi bawaan pada tipe sistem

Beberapa jenis sistem sudah mendefinisikan metode Deconstruct, menggunakan mekanisme yang sama dengan yang akan Anda gunakan untuk jenis Anda sendiri. Misalnya, System.Collections.Generic.KeyValuePair<TKey,TValue> mendukung dekonstruksi, yang membuat iterasi kamus ringkas:

foreach (var (repo, commitCount) in repoCommitCounts)
{
    Console.WriteLine($"{repo} had {commitCount:N0} commits in this snapshot.");
}

Dekonstruksi dan pencocokan pola

Metode Deconstruct juga memungkinkan pola posisional untuk jenis tersebut. Pola posisional menguji dan mendekonstruksi nilai dalam satu langkah, menggunakan sintaks dalam tanda kurung yang sama seperti pada dekonstruksi: person is ("Alice", 30) cocok dengan Person yang komponen hasil dekonstruksinya sama dengan nilai-nilai tersebut. Ini berbeda dari pola properti, yang menguji properti bernama secara langsung, seperti person is { Name: "Alice", Age: 30 }. Pola properti biasanya lebih jelas untuk bentuk objek karena nama anggota menjelaskan pengujian. Pola posisional terkuat ketika urutan sudah membawa makna, seperti dengan tuple atau nilai berurutan kecil lainnya.

Baca juga