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.
Gunakan ekspresi koleksi untuk membuat nilai koleksi umum.
Ekspresi koleksi adalah sintaks terse yang dapat Anda tetapkan ke berbagai jenis koleksi. Ekspresi koleksi berisi urutan elemen antara [ dan ] tanda kurung siku.
Referensi bahasa C# mendokumentasikan versi bahasa C# yang paling baru dirilis. Ini juga berisi dokumentasi awal untuk fitur dalam pratinjau publik untuk rilis bahasa yang akan datang.
Dokumentasi mengidentifikasi fitur apa pun yang pertama kali diperkenalkan dalam tiga versi terakhir bahasa atau dalam pratinjau publik saat ini.
Petunjuk / Saran
Untuk menemukan kapan fitur pertama kali diperkenalkan di C#, lihat artikel tentang riwayat versi bahasa C#.
Contoh berikut mendeklarasikan System.Span<T> elemen string dan menginisialisasinya ke hari dalam seminggu:
Span<string> weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
foreach (var day in weekDays)
{
Console.WriteLine(day);
}
Anda dapat mengonversi ekspresi koleksi ke berbagai jenis koleksi. Contoh pertama menunjukkan cara menginisialisasi variabel dengan menggunakan ekspresi koleksi. Kode berikut menunjukkan banyak lokasi lain di mana Anda bisa menggunakan ekspresi koleksi:
// Initialize private field:
private static readonly ImmutableArray<string> _months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
// property with expression body:
public IEnumerable<int> MaxDays =>
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
public int Sum(IEnumerable<int> values) =>
values.Sum();
public void Example()
{
// As a parameter:
int sum = Sum([1, 2, 3, 4, 5]);
}
Anda tidak dapat menggunakan ekspresi koleksi di mana konstanta waktu kompilasi diharapkan, seperti saat menginisialisasi konstanta, atau sebagai nilai default untuk argumen metode.
Kedua contoh sebelumnya menggunakan konstanta sebagai elemen ekspresi koleksi. Anda juga dapat menggunakan variabel untuk elemen, seperti yang ditunjukkan dalam contoh berikut:
string hydrogen = "H";
string helium = "He";
string lithium = "Li";
string beryllium = "Be";
string boron = "B";
string carbon = "C";
string nitrogen = "N";
string oxygen = "O";
string fluorine = "F";
string neon = "Ne";
string[] elements = [hydrogen, helium, lithium, beryllium, boron, carbon, nitrogen, oxygen, fluorine, neon];
foreach (var element in elements)
{
Console.WriteLine(element);
}
Menyebarkan elemen
Gunakan elemen.. spread untuk nilai koleksi sebaris dalam ekspresi koleksi. Contoh berikut membuat koleksi untuk alfabet lengkap dengan menggabungkan koleksi vokal, koleksi konsonan, dan huruf "y", yang dapat berupa:
string[] vowels = ["a", "e", "i", "o", "u"];
string[] consonants = ["b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "z"];
string[] alphabet = [.. vowels, .. consonants, "y"];
Elemen ..vowelsspread , ketika dievaluasi, menghasilkan lima elemen: "a", , "e", "i""o", dan "u". Elemen ..consonants spread menghasilkan 20 elemen, angka dalam consonants array. Ekspresi dalam elemen spread harus dapat dijumlahkan dengan menggunakan foreach pernyataan. Seperti yang ditunjukkan pada contoh sebelumnya, Anda dapat menggabungkan elemen spread dengan elemen individual dalam ekspresi koleksi.
Konversi
Anda dapat mengonversi ekspresi koleksi ke jenis koleksi yang berbeda, termasuk:
- System.Span<T> dan System.ReadOnlySpan<T>.
-
Array, seperti
int[]ataustring[]. - Jenis apa pun dengan metode buat yang jenis parameternya adalah
ReadOnlySpan<T>di mana ada konversi implisit dari jenis ekspresi koleksi keT. - Jenis apa pun yang mendukung penginisialisasi koleksi, seperti System.Collections.Generic.List<T>. Biasanya, persyaratan ini berarti jenis mendukung System.Collections.Generic.IEnumerable<T> dan ada metode yang dapat diakses
Adduntuk menambahkan item ke koleksi. Harus ada konversi implisit dari jenis elemen ekspresi koleksi ke jenis elemen koleksi. Untuk elemen spread, harus ada konversi implisit dari jenis elemen spread ke jenis elemen koleksi. - Salah satu antarmuka berikut:
Nota
Anda tidak dapat menggunakan ekspresi koleksi untuk menginisialisasi array sebaris. Array sebaris memerlukan sintaks inisialisasi yang berbeda.
Penting
Ekspresi koleksi selalu membuat koleksi yang menyertakan semua elemen dalam ekspresi koleksi, terlepas dari jenis target konversi. Misalnya, ketika target konversi adalah System.Collections.Generic.IEnumerable<T>, kode yang dihasilkan mengevaluasi ekspresi koleksi dan menyimpan hasilnya dalam koleksi dalam memori.
Perilaku ini berbeda dari LINQ, di mana urutan mungkin tidak dibuat sampai dijumlahkan. Anda tidak dapat menggunakan ekspresi koleksi untuk menghasilkan urutan tak terbatas yang tidak akan dijumlahkan.
Pengkompilasi menggunakan analisis statis untuk menentukan cara paling berkinerja untuk membuat koleksi yang dideklarasikan dengan ekspresi koleksi. Misalnya, ekspresi koleksi kosong, [], dapat direalisasikan seolah-olah Array.Empty<T>() target tidak akan dimodifikasi setelah inisialisasi. Ketika target adalah System.Span<T> atau System.ReadOnlySpan<T>, penyimpanan mungkin dialokasikan tumpukan.
Spesifikasi fitur ekspresi koleksi menentukan aturan yang harus diikuti pengkompilasi.
Banyak API kelebihan beban dengan beberapa jenis koleksi sebagai parameter. Karena ekspresi koleksi dapat dikonversi ke berbagai jenis ekspresi, API ini mungkin memerlukan transmisi pada ekspresi koleksi untuk menentukan konversi yang benar. Aturan konversi berikut menyelesaikan beberapa ambiguitas:
- Konversi elemen yang lebih baik lebih disukai daripada konversi jenis koleksi yang lebih baik. Dengan kata lain, jenis elemen dalam ekspresi koleksi memiliki kepentingan lebih dari jenis koleksi. Aturan ini dijelaskan dalam spesifikasi fitur untuk konversi yang lebih baik dari ekspresi koleksi.
- Konversi ke Span<T>, ReadOnlySpan<T>, atau jenis lain
ref structlebih baik daripada konversi ke jenis struct non-ref. - Konversi ke jenis noninterface lebih baik daripada konversi ke jenis antarmuka.
Saat Anda mengonversi ekspresi koleksi menjadi Span atau ReadOnlySpan, konteks aman objek rentang berasal dari konteks aman semua elemen yang disertakan dalam rentang. Untuk aturan terperinci, lihat Spesifikasi ekspresi koleksi.
Pembuat koleksi
Ekspresi koleksi berfungsi dengan jenis koleksi apa pun yang berulah dengan baik. Koleksi yang ber perilaku baik memiliki karakteristik berikut:
- Nilai
CountatauLengthpada koleksi yang dapat dihitung menghasilkan nilai yang sama dengan jumlah elemen saat dijumlahkan. - Jenis di System.Collections.Generic namespace dianggap bebas efek samping. Dengan demikian, pengkompilasi dapat mengoptimalkan skenario di mana jenis tersebut dapat digunakan sebagai nilai perantara, tetapi sebaliknya tidak diekspos.
- Panggilan ke beberapa anggota yang berlaku
.AddRange(x)pada koleksi menghasilkan nilai akhir yang sama seperti iterasi danxmenambahkan semua nilai enumerasinya satu per satu ke koleksi dengan.Add.
Semua jenis koleksi dalam runtime .NET berperilaku baik.
Peringatan
Jika jenis koleksi kustom tidak bersifat baik, perilaku tidak terdefinisi saat Anda menggunakan jenis koleksi tersebut dengan ekspresi koleksi.
Jenis Anda memilih untuk mengumpulkan dukungan ekspresi dengan menulis Create() metode dan menerapkan System.Runtime.CompilerServices.CollectionBuilderAttribute pada jenis koleksi untuk menunjukkan metode penyusun. Misalnya, pertimbangkan aplikasi yang menggunakan buffer panjang tetap 80 karakter. Kelas tersebut mungkin terlihat seperti kode berikut:
public class LineBuffer : IEnumerable<char>
{
private readonly char[] _buffer;
private readonly int _count;
public LineBuffer(ReadOnlySpan<char> buffer)
{
_buffer = new char[buffer.Length];
_count = buffer.Length;
for (int i = 0; i < _count; i++)
{
_buffer[i] = buffer[i];
}
}
public int Count => _count;
public char this[int index]
{
get
{
if (index >= _count)
throw new IndexOutOfRangeException();
return _buffer[index];
}
}
public IEnumerator<char> GetEnumerator()
{
for (int i = 0; i < _count; i++)
{
yield return _buffer[i];
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
// etc
}
Anda ingin menggunakannya dengan ekspresi koleksi seperti yang diperlihatkan dalam sampel berikut:
LineBuffer line = ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'];
Jenis mengimplementasikan LineBufferIEnumerable<char>, sehingga pengkompilasi mengenalinya sebagai kumpulan char item. Parameter jenis antarmuka yang diimplementasikan System.Collections.Generic.IEnumerable<T> menunjukkan jenis elemen. Anda perlu membuat dua tambahan ke aplikasi Anda untuk dapat menetapkan ekspresi koleksi ke LineBuffer objek. Pertama, Anda perlu membuat kelas yang berisi Create metode:
internal static class LineBufferBuilder
{
internal static LineBuffer Create(ReadOnlySpan<char> values) => new LineBuffer(values);
}
Metode Create harus mengembalikan LineBuffer objek, dan harus mengambil satu parameter dari jenis ReadOnlySpan<char>. Parameter ReadOnlySpan jenis harus cocok dengan jenis elemen koleksi. Metode penyusun yang mengembalikan koleksi generik memiliki generik ReadOnlySpan<T> sebagai parameternya. Metode harus dapat diakses dan static.
Terakhir, Anda harus menambahkan CollectionBuilderAttribute ke LineBuffer deklarasi kelas:
[CollectionBuilder(typeof(LineBufferBuilder), "Create")]
Parameter pertama menyediakan nama kelas Builder . Atribut kedua menyediakan nama metode penyusun.