Foto oleh Myburgh Roux via Pexels

Array dan List adalah dua struktur data paling umum dipakai di C# untuk menyimpan sekumpulan nilai sejenis, namun keduanya memiliki perbedaan mendasar: array memiliki ukuran tetap sejak dideklarasikan, sementara List bisa bertambah atau berkurang ukurannya secara dinamis selama program berjalan.

Array adalah struktur bawaan bahasa C# yang sangat efisien namun kaku, sementara List adalah bagian dari koleksi generic di namespace System.Collections.Generic yang menawarkan fleksibilitas jauh lebih besar lewat method seperti Add, Remove, dan Sort.

Artikel ini membahas cara mendeklarasikan dan memakai keduanya, perbedaan performa di antara mereka, serta kapan sebaiknya memilih array dibanding List atau sebaliknya untuk kebutuhan tertentu.

Mendeklarasikan dan Mengakses Array

Array memiliki ukuran tetap sesuai deklarasi awal

int[] nilaiUjian = { 80, 90, 75, 88 }; Console.WriteLine(nilaiUjian[0]); -- Expected: 80 Console.WriteLine(nilaiUjian.Length); -- Expected: 4 -- Mencoba nilaiUjian[4] akan error karena -- indeks maksimum array ini hanya 3 (0-3)
Array diakses melalui indeks yang dimulai dari 0, dan ukurannya ditentukan sejak awal deklarasi melalui properti Length yang bersifat read-only. Mencoba mengakses indeks di luar jangkauan array akan menghasilkan IndexOutOfRangeException saat program dijalankan, bukan error pada saat kompilasi.

Menambah dan Menghapus Elemen dengan List

List mendukung penambahan dan penghapusan elemen secara dinamis

List<string> daftarTugas = new List<string>(); daftarTugas.Add("Belajar C#"); daftarTugas.Add("Latihan LINQ"); daftarTugas.Remove("Belajar C#"); Console.WriteLine(daftarTugas.Count); -- Expected: 1
Berbeda dengan array, List menyediakan method Add dan Remove yang memungkinkan ukurannya berubah kapan saja selama program berjalan, cocok untuk kasus di mana jumlah data yang akan disimpan tidak diketahui sejak awal, seperti daftar tugas yang terus bertambah seiring interaksi pengguna.

Konversi Antara Array dan List

Konversi dua arah antara array dan List

int[] arrayAngka = { 1, 2, 3 }; List<int> listAngka = arrayAngka.ToList(); int[] kembaliKeArray = listAngka.ToArray(); -- Keduanya saling bisa dikonversi sesuai kebutuhan method yang dipanggil
Dalam praktiknya, developer sering perlu mengonversi antara array dan List tergantung method apa yang menerimanya sebagai parameter. Method ToList() dan ToArray() membuat konversi ini mudah dilakukan kapan pun dibutuhkan, tanpa perlu menulis loop manual untuk memindahkan elemen satu per satu.

Array Multidimensi dan Jagged Array

Array multidimensi vs jagged array dengan panjang baris berbeda

int[,] matriks = new int[2, 3] { { 1, 2, 3 }, { 4, 5, 6 } }; Console.WriteLine(matriks[1, 2]); -- Expected: 6 int[][] jaggedArray = new int[2][]; jaggedArray[0] = new int[] { 1, 2 }; jaggedArray[1] = new int[] { 3, 4, 5 };
Array multidimensi memiliki ukuran yang seragam di setiap dimensinya, sementara jagged array (array dari array) memungkinkan setiap baris memiliki panjang yang berbeda-beda, berguna untuk merepresentasikan data yang tidak seragam seperti daftar nilai siswa yang jumlah mata pelajarannya berbeda-beda per siswa.

Perbedaan Array dan List Dari Sisi Ukuran dan Performa

Array berukuran tetap, List<T> dapat tumbuh dan menyusut secara dinamis

int[] arrNilai = new int[3] { 80, 90, 75 }; // arrNilai.Length tetap 3 selamanya, tidak bisa ditambah List<int> listNilai = new List<int> { 80, 90, 75 }; listNilai.Add(100); listNilai.RemoveAt(0); Console.WriteLine(string.Join(",", listNilai)); // Output: 90,75,100

Array pada C# memiliki ukuran yang bersifat fixed sejak dideklarasikan; begitu array dengan panjang 3 dibuat, ukurannya tidak bisa diubah lagi sepanjang siklus hidup objek tersebut, dan menambah elemen baru hanya bisa dilakukan dengan membuat array baru lalu menyalin seluruh isinya. Karena ukurannya tetap dan disimpan secara contiguous di memori, operasi pembacaan elemen array melalui index tergolong sangat cepat dan memiliki overhead memori paling kecil dibanding koleksi lain.

List yang berada di namespace System.Collections.Generic dibangun di atas array internal yang secara otomatis akan diganti dengan array berukuran lebih besar (biasanya dua kali lipat) setiap kali kapasitasnya penuh, sehingga dari sisi penggunaan terasa seperti array yang bisa bertambah ukurannya secara dinamis melalui method Add, Remove, Insert, dan RemoveAt tanpa developer perlu mengelola proses resize secara manual.

Konsekuensi dari mekanisme auto-resize ini adalah List memiliki sedikit overhead memori dan waktu dibanding array murni, terutama saat penambahan elemen memicu proses realokasi array internal. Untuk skenario di mana jumlah elemen sudah diketahui pasti sejak awal dan tidak akan berubah, array tetap menjadi pilihan yang lebih efisien, sedangkan List lebih cocok untuk koleksi data yang ukurannya dinamis mengikuti alur program.

Multidimensional Array dan Jagged Array untuk Data Tabular

Array dua dimensi (rectangular) vs array berisi array (jagged)

// Multidimensional array (rectangular), ukuran setiap baris sama int[,] matriksNilai = new int[2, 3] { { 80, 90, 75 }, { 60, 70, 85 } }; Console.WriteLine(matriksNilai[1, 2]); // Output: 85 // Jagged array, setiap baris bisa berbeda panjang int[][] nilaiPerKelas = new int[2][]; nilaiPerKelas[0] = new int[] { 80, 90 }; nilaiPerKelas[1] = new int[] { 60, 70, 85, 95 }; Console.WriteLine(nilaiPerKelas[1][3]); // Output: 95

Selain array satu dimensi biasa, C# mendukung multidimensional array (rectangular array) yang dideklarasikan dengan tanda koma di dalam tanda kurung siku seperti int[,], di mana setiap baris wajib memiliki jumlah kolom yang identik. Struktur ini cocok merepresentasikan data tabular yang benar-benar berbentuk grid sempurna, misalnya matriks matematika atau papan permainan seperti tic-tac-toe yang selalu memiliki ukuran baris dan kolom yang sama.

Jagged array, dideklarasikan dengan int[][], sebenarnya adalah array yang setiap elemennya merupakan array lain, sehingga masing-masing baris dapat memiliki panjang yang berbeda-beda secara independen, seperti terlihat pada nilaiPerKelas di mana baris pertama memiliki dua nilai sedangkan baris kedua memiliki empat nilai. Fleksibilitas ini membuat jagged array lebih sering dipakai dibanding multidimensional array ketika data yang direpresentasikan memang tidak seragam jumlah elemennya di setiap barisnya.

Dari sisi performa, jagged array umumnya sedikit lebih cepat diakses dibanding multidimensional array karena CLR memperlakukannya sebagai kumpulan array satu dimensi biasa yang sudah sangat dioptimalkan, sedangkan multidimensional array memerlukan perhitungan index tambahan untuk menentukan posisi elemen dalam struktur grid-nya. Pemilihan keduanya sebaiknya didasarkan pada bentuk data asli, bukan semata-mata pertimbangan performa, karena perbedaannya baru terasa signifikan pada data berukuran sangat besar. Untuk kasus yang membutuhkan struktur tabular dengan kolom bernama dan tipe data yang berbeda-beda di setiap kolomnya, DataTable atau koleksi List berisi class kustom biasanya menjadi pilihan yang lebih tepat dibanding memaksakan array dua dimensi yang hanya mendukung satu tipe data seragam.

Membuat Indexer Kustom agar Class Bisa Diakses Seperti Array

public class Inventaris { private readonly Dictionary<string, int> _stok = new(); public int this[string kodeBarang] { get => _stok.TryGetValue(kodeBarang, out var jumlah) ? jumlah : 0; set => _stok[kodeBarang] = value; } } var inv = new Inventaris(); inv["BRG001"] = 50; Console.WriteLine(inv["BRG001"]); Console.WriteLine(inv["BRG999"]); // Output: // 50 // 0

Indexer adalah anggota class khusus yang didefinisikan dengan sintaks this[parameter] sehingga instance class bisa diakses menggunakan notasi kurung siku layaknya array atau dictionary bawaan, lengkap dengan blok get dan set yang bisa berisi logika tambahan seperti validasi, nilai default, atau pencatatan log setiap kali data diakses atau diubah, bukan sekadar menyimpan dan mengambil nilai mentah seperti array biasa. Parameter indexer juga tidak harus berupa angka seperti pada array konvensional, melainkan bisa berupa string, enum, atau tipe lain yang relevan dengan domain data yang direpresentasikan oleh class tersebut.

Pada contoh di atas, indexer pada class Inventaris mengembalikan nol jika kode barang belum terdaftar di dalam dictionary internal, alih-alih melempar exception seperti perilaku default Dictionary saat key tidak ditemukan. Pola ini berguna untuk membungkus struktur data internal agar pemakai class mendapatkan antarmuka akses yang lebih aman, konsisten, dan intuitif tanpa mengekspos detail implementasi penyimpanan data yang sebenarnya digunakan di balik layar, baik itu Dictionary, array, maupun struktur lain yang bisa diganti kapan saja tanpa mempengaruhi kode pemanggil.

Kesalahan Umum yang Sering Terjadi

Mengakses Indeks di Luar Jangkauan Array

Lupa bahwa indeks array dimulai dari 0 dan maksimum adalah Length - 1 sering menyebabkan IndexOutOfRangeException, terutama saat melakukan loop dengan kondisi yang kurang tepat seperti i <= Length.

Menggunakan Array Saat Ukuran Data Tidak Pasti

Memilih array untuk data yang jumlahnya bisa berubah-ubah memaksa developer membuat array baru dan menyalin seluruh data lama setiap kali ukuran perlu diubah, sebuah proses yang tidak efisien dibanding memakai List yang menangani ini secara otomatis.

Tidak Menyadari Overhead List Dibanding Array untuk Data Statis

List memiliki sedikit overhead memori dan performa dibanding array murni karena struktur internalnya yang lebih kompleks, sehingga untuk data yang ukurannya benar-benar tetap dan diketahui sejak awal, array bisa jadi pilihan yang sedikit lebih efisien.

Kapan Pendekatan Ini Tidak Cocok Dipakai

Array memberikan performa sedikit lebih baik dan penggunaan memori lebih efisien untuk data dengan ukuran tetap yang diketahui sejak awal, seperti koordinat 3D atau hari dalam seminggu.

List memberikan fleksibilitas yang jauh lebih besar untuk data yang ukurannya berubah-ubah seiring waktu, dengan trade-off sedikit overhead performa dan memori dibanding array murni, namun kemudahan ini biasanya jauh lebih berharga dibanding penghematan performa yang minim tersebut.

Ringkasan

Array cocok dipakai ketika ukuran data sudah pasti dan tidak akan berubah, sementara List jauh lebih fleksibel untuk data yang jumlahnya dinamis. Pahami perbedaan keduanya serta kemudahan konversi di antara mereka agar bisa memilih struktur data yang paling sesuai dengan kebutuhan setiap kasus.

Seri Belajar C# Fundamental:

← Sebelumnya: Pengantar OOP dan Cara Pembuatan Class (sudah ada)

→ Selanjutnya: Method dan Parameter di C#