Koleksi

Runtime .NET menyediakan banyak jenis koleksi yang menyimpan dan mengelola grup objek terkait. Beberapa jenis koleksi, seperti System.Array, System.Span<T>, dan System.Memory<T> dikenali dalam bahasa C#. Selain itu, antarmuka seperti System.Collections.Generic.IEnumerable<T> dikenali dalam bahasa untuk menghitung elemen koleksi.

Koleksi menyediakan cara yang fleksibel untuk bekerja dengan sekelompok objek. Anda dapat mengklasifikasikan berbagai koleksi berdasarkan karakteristik ini:

  • Akses elemen: Setiap koleksi dapat dijumlahkan untuk mengakses setiap elemen secara berurutan. Beberapa koleksi mengakses elemen menurut indeks, posisi elemen dalam koleksi yang diurutkan. Contoh yang paling umum adalah System.Collections.Generic.List<T>. Koleksi lain mengakses elemen menurut kunci, di mana nilai dikaitkan dengan satu kunci. Contoh yang paling umum adalah System.Collections.Generic.Dictionary<TKey,TValue>. Anda memilih di antara jenis koleksi ini berdasarkan cara aplikasi Anda mengakses elemen.
  • Profil performa: Setiap koleksi memiliki profil performa yang berbeda untuk tindakan seperti menambahkan elemen, menemukan elemen, atau menghapus elemen. Anda dapat memilih jenis koleksi berdasarkan operasi yang paling banyak digunakan di aplikasi Anda.
  • Tumbuh dan menyusut secara dinamis: Sebagian besar koleksi yang mendukung penambahan atau penghapusan elemen secara dinamis. Terutama, Array, System.Span<T>, dan System.Memory<T> tidak.

Selain karakteristik tersebut, runtime menyediakan koleksi khusus yang mencegah penambahan atau penghapusan elemen atau memodifikasi elemen koleksi. Koleksi khusus lainnya memberikan keamanan untuk akses bersamaan di aplikasi multi-utas.

Anda dapat menemukan semua jenis koleksi dalam referensi .NET API. Untuk informasi selengkapnya, lihat Jenis Koleksi yang Umum Digunakan dan Memilih Kelas Koleksi.

Catatan

Untuk contoh dalam artikel ini, Anda mungkin perlu menambahkan menggunakan direktif untuk System.Collections.Generic namespace layanan dan System.Linq .

Array diwakili oleh System.Array dan memiliki dukungan sintaks dalam bahasa C#. Sintaks ini menyediakan deklarasi yang lebih ringkas untuk variabel array.

System.Span<T> adalah ref struct jenis yang menyediakan rekam jepret atas urutan elemen tanpa menyalin elemen tersebut. Kompilator memberlakukan aturan keselamatan untuk memastikan Span tidak dapat diakses setelah urutan referensinya tidak lagi berada dalam cakupan. Ini digunakan di banyak API .NET untuk meningkatkan performa. Memory<T> memberikan perilaku serupa ketika Anda tidak dapat menggunakan ref struct jenis.

Dimulai dengan C# 12, semua jenis koleksi dapat diinisialisasi menggunakan ekspresi Koleksi.

Koleksi yang dapat diindeks

Koleksi yang dapat diindeks adalah salah satu tempat Anda dapat mengakses setiap elemen menggunakan indeksnya. Indeksnya adalah jumlah elemen sebelum dalam urutan. Oleh karena itu, referensi elemen menurut indeks 0 adalah elemen pertama, indeks 1 adalah yang kedua, dan sebagainya. Contoh-contoh ini menggunakan List<T> kelas . Ini adalah koleksi yang paling umum diindeks.

Contoh berikut membuat dan menginisialisasi daftar string, menghapus elemen, dan menambahkan elemen ke akhir daftar. Setelah setiap modifikasi, iterasi melalui string dengan menggunakan pernyataan foreach atau perulangan for :

// Create a list of strings by using a
// collection initializer.
List<string> salmons = ["chinook", "coho", "pink", "sockeye"];

// Iterate through the list.
foreach (var salmon in salmons)
{
    Console.Write(salmon + " ");
}
// Output: chinook coho pink sockeye

// Remove an element from the list by specifying
// the object.
salmons.Remove("coho");


// Iterate using the index:
for (var index = 0; index < salmons.Count; index++)
{
    Console.Write(salmons[index] + " ");
}
// Output: chinook pink sockeye

// Add the removed element
salmons.Add("coho");
// Iterate through the list.
foreach (var salmon in salmons)
{
    Console.Write(salmon + " ");
}
// Output: chinook pink sockeye coho

Contoh berikut menghapus elemen dari daftar menurut indeks. Alih-alih foreach pernyataan, ia menggunakan for pernyataan yang berulang dalam urutan turun. Metode ini RemoveAt menyebabkan elemen setelah elemen yang dihapus memiliki nilai indeks yang lebih rendah.

List<int> numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// Remove odd numbers.
for (var index = numbers.Count - 1; index >= 0; index--)
{
    if (numbers[index] % 2 == 1)
    {
        // Remove the element by specifying
        // the zero-based index in the list.
        numbers.RemoveAt(index);
    }
}

// Iterate through the list.
// A lambda expression is placed in the ForEach method
// of the List(T) object.
numbers.ForEach(
    number => Console.Write(number + " "));
// Output: 0 2 4 6 8

Untuk jenis elemen dalam List<T>, Anda juga dapat menentukan kelas Anda sendiri. Dalam contoh berikut, kelas Galaxy yang digunakan oleh List<T> ditentukan dalam kode.

private static void IterateThroughList()
{
    var theGalaxies = new List<Galaxy>
    {
        new (){ Name="Tadpole", MegaLightYears=400},
        new (){ Name="Pinwheel", MegaLightYears=25},
        new (){ Name="Milky Way", MegaLightYears=0},
        new (){ Name="Andromeda", MegaLightYears=3}
    };

    foreach (Galaxy theGalaxy in theGalaxies)
    {
        Console.WriteLine(theGalaxy.Name + "  " + theGalaxy.MegaLightYears);
    }

    // Output:
    //  Tadpole  400
    //  Pinwheel  25
    //  Milky Way  0
    //  Andromeda  3
}

public class Galaxy
{
    public string Name { get; set; }
    public int MegaLightYears { get; set; }
}

Koleksi pasangan kunci/nilai

Contoh-contoh ini menggunakan Dictionary<TKey,TValue> kelas . Ini adalah koleksi kamus yang paling umum. Koleksi kamus memungkinkan Anda mengakses elemen dalam koleksi dengan menggunakan kunci setiap elemen. Setiap penambahan ke kamus terdiri dari nilai dan kunci terkaitnya.

Contoh berikut membuat koleksi Dictionary dan mengulang melalui kamus dengan menggunakan pernyataan foreach.

private static void IterateThruDictionary()
{
    Dictionary<string, Element> elements = BuildDictionary();

    foreach (KeyValuePair<string, Element> kvp in elements)
    {
        Element theElement = kvp.Value;

        Console.WriteLine("key: " + kvp.Key);
        Console.WriteLine("values: " + theElement.Symbol + " " +
            theElement.Name + " " + theElement.AtomicNumber);
    }
}

public class Element
{
    public required string Symbol { get; init; }
    public required string Name { get; init; }
    public required int AtomicNumber { get; init; }
}

private static Dictionary<string, Element> BuildDictionary() =>
    new ()
    {
        {"K",
            new (){ Symbol="K", Name="Potassium", AtomicNumber=19}},
        {"Ca",
            new (){ Symbol="Ca", Name="Calcium", AtomicNumber=20}},
        {"Sc",
            new (){ Symbol="Sc", Name="Scandium", AtomicNumber=21}},
        {"Ti",
            new (){ Symbol="Ti", Name="Titanium", AtomicNumber=22}}
    };

Contoh berikut menggunakan metode ContainsKey dan properti Item[] dari Dictionary untuk dapat dengan cepat menemukan item berdasarkan kunci. Properti Item memungkinkan Anda mengakses item dalam koleksi elements dengan menggunakan elements[symbol] di C#.

if (elements.ContainsKey(symbol) == false)
{
    Console.WriteLine(symbol + " not found");
}
else
{
    Element theElement = elements[symbol];
    Console.WriteLine("found: " + theElement.Name);
}

Contoh berikut menggunakan TryGetValue metode untuk menemukan item dengan cepat berdasarkan kunci.

if (elements.TryGetValue(symbol, out Element? theElement) == false)
    Console.WriteLine(symbol + " not found");
else
    Console.WriteLine("found: " + theElement.Name);

Iterator

Pengulang digunakan untuk melakukan perulangan kustom terhadap koleksi. Iterator dapat menjadi metode atau pengakses get. Iterator menggunakan pernyataan pengembalian hasil untuk mengembalikan setiap elemen koleksi satu per satu.

Anda memanggil iterator dengan menggunakan pernyataan foreach. Setiap perulangan dari perulangan foreach akan memanggil pengulang. Ketika pernyataan yield return tercapai dalam pengulang, ekspresi akan ditampilkan, dan lokasi dalam kode saat ini akan dipertahankan. Eksekusi dimulai ulang dari lokasi tersebut saat iterator dipanggil lain kali.

Untuk informasi selengkapnya, lihat Iterator (C#).

Contoh berikut menggunakan metode pengulang. Metode iterator memiliki pernyataan yield return yang ada di dalam perulangan for. Dalam metode ListEvenNumbers, setiap iterasi dari isi pernyataan foreach membuat panggilan ke metode iterator, yang akan berlanjut ke pernyataan yield return berikutnya.

private static void ListEvenNumbers()
{
    foreach (int number in EvenSequence(5, 18))
    {
        Console.Write(number.ToString() + " ");
    }
    Console.WriteLine();
    // Output: 6 8 10 12 14 16 18
}

private static IEnumerable<int> EvenSequence(
    int firstNumber, int lastNumber)
{
    // Yield even numbers in the range.
    for (var number = firstNumber; number <= lastNumber; number++)
    {
        if (number % 2 == 0)
        {
            yield return number;
        }
    }
}

LINQ dan koleksi

Kueri terintegrasi bahasa (LINQ) dapat digunakan untuk mengakses koleksi. Kueri LINQ menyediakan kemampuan pemfilteran, pengurutan, dan pengelompokan. Untuk informasi selengkapnya, lihat Mulai menggunakan LINQ di C#.

Contoh berikut menjalankan kueri LINQ terhadap List generik. Kueri LINQ menampilkan koleksi berbeda yang berisi hasilnya.

private static void ShowLINQ()
{
    List<Element> elements = BuildList();

    // LINQ Query.
    var subset = from theElement in elements
                 where theElement.AtomicNumber < 22
                 orderby theElement.Name
                 select theElement;

    foreach (Element theElement in subset)
    {
        Console.WriteLine(theElement.Name + " " + theElement.AtomicNumber);
    }

    // Output:
    //  Calcium 20
    //  Potassium 19
    //  Scandium 21
}

private static List<Element> BuildList() => new()
    {
        { new(){ Symbol="K", Name="Potassium", AtomicNumber=19}},
        { new(){ Symbol="Ca", Name="Calcium", AtomicNumber=20}},
        { new(){ Symbol="Sc", Name="Scandium", AtomicNumber=21}},
        { new(){ Symbol="Ti", Name="Titanium", AtomicNumber=22}}
    };