Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Tuple menyediakan struktur data ringan untuk beberapa anggota dalam satu struktur. Mereka adalah pilihan yang lebih disukai dibandingkan dengan tipe anonim. Tuple memberikan performa yang lebih baik, mendukung dekonstruksi, dan menawarkan sintaks yang lebih fleksibel.
Jenis anonim menyediakan cara mudah untuk merangkum sekumpulan properti baca-saja ke dalam satu objek tanpa harus secara eksplisit menentukan jenis terlebih dahulu. Pengkompilasi menghasilkan nama jenis, dan tidak tersedia di tingkat kode sumber. Pengkompilasi menyimpulkan jenis setiap properti. Gunakan jenis anonim terutama saat Anda memerlukan dukungan pohon ekspresi atau saat bekerja dengan kode yang memerlukan jenis referensi.
Jenis tuple vs tipe anonim
Kedua tipe tuple dan tipe anonim memungkinkan Anda mengelompokkan beberapa nilai tanpa mendefinisikan tipe yang dinamai. Namun, tuple memiliki dukungan bahasa yang lebih baik dan dikompilasi ke struktur data yang lebih efisien. Tabel berikut ini meringkas perbedaan utama:
| Fitur | Jenis anonim | Tuple |
|---|---|---|
| Tipe | Jenis referensi (class) |
Jenis nilai (struct) |
| Performance | Alokasi timbunan | Alokasi tumpukan (performa yang lebih baik) |
| Mutability | Properti baca-saja | Bidang yang dapat diubah |
| Dekonstruksi | Tidak didukung | Didukung |
| Pohon Ekspresi | Didukung | Tidak didukung |
| Pengubah akses | internal |
public |
| Nama anggota | Diperlukan atau disimpulkan | Opsional (dengan nama default seperti Item1, Item2) |
Kapan menggunakan tuple
Gunakan tuple saat:
- Anda memerlukan kinerja yang lebih baik melalui alokasi stack.
- Anda ingin mendekonstruksi nilai menjadi variabel terpisah.
- Anda mengembalikan beberapa nilai dari metode .
- Anda tidak memerlukan dukungan pohon ekspresi.
Contoh berikut menunjukkan bagaimana tuple menyediakan fungsionalitas serupa dengan jenis anonim dengan sintaks yang lebih bersih:
// Tuple with named elements.
var tupleProduct = (Name: "Widget", Price: 19.99M);
Console.WriteLine($"Tuple: {tupleProduct.Name} costs ${tupleProduct.Price}");
// Equivalent example using anonymous types.
var anonymousProduct = new { Name = "Widget", Price = 19.99M };
Console.WriteLine($"Anonymous: {anonymousProduct.Name} costs ${anonymousProduct.Price}");
Dekonstruksi tuple
Anda dapat mendekonstruksi tuple menjadi variabel terpisah, yang menyediakan cara mudah untuk bekerja dengan elemen tuple individual. C# mendukung beberapa cara untuk mendekonstruksi tuple:
static (string Name, int Age, string City) GetPersonInfo()
{
return ("Alice", 30, "Seattle");
}
// Deconstruct using var for all variables
var (name, age, city) = GetPersonInfo();
Console.WriteLine($"{name} is {age} years old and lives in {city}");
// Output: Alice is 30 years old and lives in Seattle
// Deconstruct with explicit types
(string personName, int personAge, string personCity) = GetPersonInfo();
Console.WriteLine($"{personName}, {personAge}, {personCity}");
// Deconstruct into existing variables
string existingName;
int existingAge;
string existingCity;
(existingName, existingAge, existingCity) = GetPersonInfo();
// Deconstruct and discard unwanted values using the discard pattern (_)
var (name2, _, city2) = GetPersonInfo();
Console.WriteLine($"{name2} lives in {city2}");
// Output: Alice lives in Seattle
Dekonstruksi berguna dalam skenario perulangan dan pencocokan pola.
var people = new List<(string Name, int Age)>
{
("Bob", 25),
("Carol", 35),
("Dave", 40)
};
foreach (var (personName2, personAge2) in people)
{
Console.WriteLine($"{personName2} is {personAge2} years old");
}
Tuple sebagai jenis pengembalian metode
Kasus penggunaan umum untuk tuple adalah sebagai jenis pengembalian metode. Alih-alih menentukan out parameter, Anda dapat mengelompokkan hasil metode dalam sebuah tuple. Anda tidak dapat mengembalikan jenis anonim dari metode, karena tidak memiliki nama, dan jenis pengembalian tidak dapat dideklarasikan.
Contoh berikut menunjukkan penggunaan tuple dengan pencarian dalam kamus untuk mengembalikan rentang konfigurasi.
var configLookup = new Dictionary<int, (int Min, int Max)>()
{
[2] = (4, 10),
[4] = (10, 20),
[6] = (0, 23)
};
if (configLookup.TryGetValue(4, out (int Min, int Max) range))
{
Console.WriteLine($"Found range: min is {range.Min}, max is {range.Max}");
}
// Output: Found range: min is 10, max is 20
Pola ini berguna saat bekerja dengan metode yang perlu mengembalikan indikator keberhasilan dan beberapa nilai hasil. Tuple memungkinkan Anda menggunakan bidang bernama (Min dan Max) alih-alih nama generik seperti Item1 dan Item2, membuat kode lebih mudah dibaca dan didokumentasikan sendiri.
Kapan menggunakan jenis anonim
Gunakan jenis anonim saat:
- Anda bekerja dengan pohon ekspresi (misalnya, di beberapa penyedia Microsoft Language-Integrated Query (LINQ).
- Anda memerlukan objek untuk menjadi jenis referensi.
Skenario yang paling umum adalah menginisialisasi jenis anonim dengan properti dari jenis lain. Dalam contoh berikut, asumsikan bahwa ada kelas bernama Product. Kelas Product mencakup properti Color dan Price, bersama dengan properti lain yang tidak Anda minati.
class Product
{
public string? Color { get; init; }
public decimal Price { get; init; }
public string? Name { get; init; }
public string? Category { get; init; }
public string? Size { get; init; }
}
Deklarasi jenis anonim dimulai dengan new operator bersama dengan penginisialisasi objek. Deklarasi menginisialisasi jenis baru yang hanya menggunakan dua properti dari Product. Jenis anonim biasanya digunakan dalam select klausa ekspresi kueri untuk mengembalikan jumlah data yang lebih kecil. Untuk informasi selengkapnya tentang kueri, lihat LINQ di C#.
Jika Anda tidak menentukan nama anggota dalam jenis anonim, pengompilasi memberi anggota tipe anonim nama yang sama dengan properti yang digunakan untuk menginisialisasinya. Anda memberikan nama untuk properti yang sedang diinisialisasi dengan ekspresi, seperti yang diperlihatkan dalam contoh sebelumnya.
Dalam contoh berikut, nama properti dari jenis anonimnya adalah Color dan Price. Instans adalah item dari products kumpulan jenis Product :
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
Penginisialisasi proyeksi dengan jenis anonim
Jenis anonim mendukung penginisialisasi proyeksi, yang memungkinkan Anda menggunakan variabel atau parameter lokal secara langsung tanpa secara eksplisit menentukan nama anggota. Pengkompilasi menyimpulkan nama anggota dari nama variabel. Contoh berikut menunjukkan sintaks yang disederhanakan ini:
// Explicit member names.
var personExplicit = new { FirstName = "Kyle", LastName = "Mit" };
// Projection initializers (inferred member names).
var firstName = "Kyle";
var lastName = "Mit";
var personInferred = new { firstName, lastName };
// Both create equivalent anonymous types with the same property names.
Console.WriteLine($"Explicit: {personExplicit.FirstName} {personExplicit.LastName}");
Console.WriteLine($"Inferred: {personInferred.firstName} {personInferred.lastName}");
Sintaks yang disederhanakan ini berguna saat membuat jenis anonim dengan banyak properti:
var title = "Software Engineer";
var department = "Engineering";
var salary = 75000;
// Using projection initializers.
var employee = new { title, department, salary };
// Equivalent to explicit syntax:
// var employee = new { title = title, department = department, salary = salary };
Console.WriteLine($"Title: {employee.title}, Department: {employee.department}, Salary: {employee.salary}");
Nama anggota tidak disimpulkan dalam kasus berikut:
- Nama kandidat menduplikasi anggota properti lain dalam jenis anonim yang sama, secara eksplisit atau implisit.
- Nama kandidat bukan pengidentifikasi yang valid (misalnya, berisi spasi atau karakter khusus).
Dalam kasus ini, Anda harus secara eksplisit menentukan nama anggota.
Petunjuk / Saran
Anda dapat menggunakan aturan gaya .NET IDE0037 untuk memberlakukan apakah nama anggota yang disimpulkan atau eksplisit lebih diutamakan.
Anda juga dapat menentukan bidang dengan menggunakan objek jenis lain: kelas, struct, atau bahkan jenis anonim lainnya. Untuk melakukan ini, gunakan variabel yang menyimpan objek ini. Contoh berikut menunjukkan dua jenis anonim yang menggunakan tipe yang didefinisikan pengguna yang sudah diinstansiasi. Dalam kedua kasus, bidang product dalam jenis anonim shipment dan shipmentWithBonus berjenis Product dan berisi nilai default dari setiap bidang. Bidang bonus ini berjenis anonim yang dibuat oleh pengompilasi.
var product = new Product();
var bonus = new { note = "You won!" };
var shipment = new { address = "Nowhere St.", product };
var shipmentWithBonus = new { address = "Somewhere St.", product, bonus };
Biasanya, ketika Anda menggunakan jenis anonim untuk menginisialisasi variabel, Anda mendeklarasikan variabel sebagai variabel lokal yang diketik secara implisit dengan menggunakan var. Anda tidak dapat menentukan nama jenis dalam deklarasi variabel karena hanya pengompilasi yang memiliki akses ke nama yang mendasar dari jenis anonim. Untuk informasi selengkapnya tentang var, lihat Variabel Lokal yang Dijeniskan secara Implisit.
Anda dapat membuat lapisan elemen yang dijeniskan secara anonim dengan menggabungkan variabel lokal yang dijeniskan secara implisit dan lapisan yang dijeniskan secara implisit, seperti yang ditunjukkan dalam contoh berikut.
var anonArray = new[] { new { name = "apple", diam = 4 }, new { name = "grape", diam = 1 }};
Jenis anonim adalah class jenis yang berasal langsung dari object, dan Anda tidak dapat melemparkannya ke jenis apa pun kecuali object. Pengompilasi menyediakan nama untuk setiap jenis anonim, meskipun aplikasi Anda tidak dapat mengaksesnya. Dari perspektif runtime bahasa umum, jenis anonim tidak berbeda dari jenis referensi lainnya.
Jika dua atau lebih penginisialisasi objek anonim dalam perakitan menentukan urutan properti yang berada dalam urutan yang sama dan yang memiliki nama dan jenis yang sama, pengompilasi memperlakukan objek sebagai instans dengan jenis yang sama. Mereka berbagi informasi jenis yang dihasilkan kompilator yang sama.
Jenis anonim mendukung mutasi non-destruktif dalam bentuk dengan ekspresi. Fitur ini memungkinkan Anda membuat instans baru dari jenis anonim di mana satu atau beberapa properti memiliki nilai baru:
var apple = new { Item = "apples", Price = 1.35 };
var onSale = apple with { Price = 0.79 };
Console.WriteLine(apple);
Console.WriteLine(onSale);
Anda tidak dapat mendeklarasikan bidang, properti, peristiwa, atau jenis pengembalian metode sebagai memiliki jenis anonim. Demikian pula, Anda tidak dapat mendeklarasikan parameter formal metode, properti, konstruktor, atau pengindeks sebagai memiliki jenis anonim. Untuk meneruskan jenis anonim, atau koleksi yang berisi jenis anonim, sebagai argumen ke metode, Anda dapat mendeklarasikan parameter sebagai jenis object. Tetapi, menggunakan object untuk jenis anonim mengalahkan tujuan pengetikan yang kuat. Jika Anda harus menyimpan hasil kueri atau meneruskannya di luar batas metode, pertimbangkan untuk menggunakan struktur atau kelas bernama biasa alih-alih jenis anonim.
Karena metode Equals dan GetHashCode pada jenis anonim didefinisikan dalam hal metode Equals dan GetHashCode dari properti, dua instans dengan jenis anonim yang sama hanya jika semua propertinya sama.
Catatan
Tingkat aksesibilitas jenis anonim adalah internal. Oleh karena itu, dua jenis anonim yang didefinisikan dalam rakitan yang berbeda tidak memiliki jenis yang sama.
Oleh karena itu, instans jenis anonim tidak dapat sama satu sama lain ketika didefinisikan dalam rakitan yang berbeda, bahkan ketika memiliki semua propertinya sama.
Jenis anonim mengambil alih ToString metode , menggabungkan nama dan ToString output setiap properti yang dikelilingi oleh kurung kurawal.
var v = new { Title = "Hello", Age = 24 };
Console.WriteLine(v.ToString()); // "{ Title = Hello, Age = 24 }"