Bagikan melalui


Pedoman untuk Koleksi

Catatan

Konten ini dicetak ulang oleh izin Pearson Education, Inc. dari Panduan Desain Kerangka Kerja: Konvensi, Idiom, dan Pola untuk Pustaka .NET yang Dapat Digunakan Kembali, Edisi ke-2. Edisi itu diterbitkan pada tahun 2008, dan buku tersebut telah sepenuhnya direvisi pada edisi ketiga. Beberapa informasi di halaman ini mungkin sudah kedaluarsa.

Setiap jenis yang dirancang khusus untuk memanipulasi grup objek yang memiliki beberapa karakteristik umum dapat dianggap sebagai koleksi. Hampir selalu sesuai untuk jenis tersebut untuk mengimplementasikan IEnumerable atau IEnumerable<T>, jadi di bagian ini kami hanya mempertimbangkan jenis yang mengimplementasikan satu atau kedua antarmuka tersebut menjadi koleksi.

❌ JANGAN gunakan koleksi berjenis lemah di API publik.

Jenis semua nilai pengembalian dan parameter yang mewakili item koleksi harus merupakan jenis item yang tepat, bukan jenis dasarnya (ini hanya berlaku untuk anggota publik koleksi).

❌ JANGAN gunakan ArrayList atau List<T> di API publik.

Jenis ini adalah struktur data yang dirancang untuk digunakan dalam implementasi internal, bukan di API publik. List<T> dioptimalkan untuk performa dan daya dengan biaya kebersihan API dan fleksibilitas. Misalnya, jika Anda mengembalikan List<T>, Anda tidak akan pernah dapat menerima pemberitahuan ketika kode klien memodifikasi koleksi. Selain itu, List<T> mengekspos banyak anggota, seperti BinarySearch, yang tidak berguna atau berlaku dalam banyak skenario. Dua bagian berikut menjelaskan jenis (abstraksi) yang dirancang khusus untuk digunakan dalam API publik.

❌ JANGAN gunakan Hashtable atau Dictionary<TKey,TValue> di API publik.

Jenis ini adalah struktur data yang dirancang untuk digunakan dalam implementasi internal. API publik harus menggunakan IDictionary, IDictionary <TKey, TValue>, atau jenis kustom yang mengimplementasikan salah satu atau kedua antarmuka.

❌ JANGAN gunakan IEnumerator<T>, IEnumerator, atau jenis lain yang mengimplementasikan salah satu antarmuka ini, kecuali sebagai jenis GetEnumerator pengembalian metode.

Jenis yang mengembalikan enumerator dari metode selain GetEnumerator tidak dapat digunakan dengan foreach pernyataan.

❌ JANGAN terapkan baik IEnumerator<T> dan IEnumerable<T> pada jenis yang sama. Hal yang sama berlaku untuk antarmuka IEnumerator nongenerik dan IEnumerable.

Parameter Koleksi

✔️ Gunakan jenis yang paling tidak terspesialisasi sebagai jenis parameter. Sebagian besar anggota mengambil koleksi sebagai parameter menggunakan IEnumerable<T> antarmuka.

❌ AVOID menggunakan ICollection<T> atau ICollection sebagai parameter hanya untuk mengakses Count properti.

Sebagai gantinya, pertimbangkan untuk menggunakan IEnumerable<T> atau IEnumerable dan secara dinamis memeriksa apakah objek mengimplementasikan ICollection<T> atau ICollection.

Properti Koleksi dan Nilai Pengembalian

❌ JANGAN menyediakan properti koleksi yang dapat diatur.

Pengguna dapat mengganti isi koleksi dengan membersihkan koleksi terlebih dahulu dan kemudian menambahkan konten baru. Jika mengganti seluruh koleksi adalah skenario umum, pertimbangkan untuk menyediakan AddRange metode pada koleksi.

✔️ DO menggunakan Collection<T> atau subkelas Collection<T> untuk properti atau mengembalikan nilai yang mewakili koleksi baca/tulis.

Jika Collection<T> tidak memenuhi beberapa persyaratan (misalnya, koleksi tidak boleh mengimplementasikan IList), gunakan koleksi kustom dengan menerapkan IEnumerable<T>, ICollection<T>, atau IList<T>.

✔️ DO menggunakan ReadOnlyCollection<T>, subkelas dari ReadOnlyCollection<T>, atau dalam kasus IEnumerable<T> yang jarang terjadi untuk properti atau mengembalikan nilai yang mewakili koleksi baca-saja.

Secara umum, lebih memilih ReadOnlyCollection<T>. Jika tidak memenuhi beberapa persyaratan (misalnya, koleksi tidak boleh mengimplementasikan IList), gunakan koleksi kustom dengan menerapkan IEnumerable<T>, ICollection<T>, atau IList<T>. Jika Anda menerapkan koleksi baca-saja kustom, terapkan ICollection<T>.IsReadOnly untuk mengembalikan true.

Dalam kasus ketika Anda yakin bahwa satu-satunya skenario yang ingin Anda dukung adalah iterasi hanya ke depan, Anda cukup menggunakan IEnumerable<T>.

✔️ PERTIMBANGKAN untuk menggunakan subkelas koleksi dasar generik alih-alih menggunakan koleksi secara langsung.

Hal ini memungkinkan untuk nama yang lebih baik dan untuk menambahkan anggota pembantu yang tidak hadir pada jenis koleksi dasar. Ini terutama berlaku untuk API tingkat tinggi.

✔️ PERTIMBANGKAN untuk mengembalikan subkelas Collection<T> atau ReadOnlyCollection<T> dari metode dan properti yang sangat umum digunakan.

Ini akan memungkinkan Anda untuk menambahkan metode pembantu atau mengubah implementasi pengumpulan di masa mendatang.

✔️ PERTIMBANGKAN untuk menggunakan koleksi kunci jika item yang disimpan dalam koleksi memiliki kunci unik (nama, ID, dll.). Koleksi kunci adalah koleksi yang dapat diindeks oleh bilangan bulat dan kunci dan biasanya diimplementasikan dengan mewarisi dari KeyedCollection<TKey,TItem>.

Koleksi kunci biasanya memiliki jejak memori yang lebih besar dan tidak boleh digunakan jika overhead memori melebihi manfaat memiliki kunci.

❌ JANGAN mengembalikan nilai null dari properti koleksi atau dari metode yang mengembalikan koleksi. Kembalikan koleksi kosong atau array kosong sebagai gantinya.

Aturan umumnya adalah bahwa koleksi atau array null dan kosong (0 item) harus diperlakukan sama.

Snapshot Versus Koleksi Langsung

Koleksi yang mewakili keadaan di beberapa titik waktu disebut koleksi snapshot. Misalnya, kumpulan yang berisi baris yang dikembalikan dari kueri database akan menjadi snapshot. Koleksi yang selalu mewakili keadaan saat ini disebut koleksi langsung. Misalnya, koleksi ComboBox item adalah koleksi langsung.

❌ JANGAN mengembalikan koleksi snapshot dari properti. Properti harus mengembalikan koleksi langsung.

Pengambil properti harus menjadi operasi yang sangat ringan. Mengembalikan snapshot memerlukan pembuatan salinan koleksi internal dalam operasi O(n).

✔️ DO menggunakan koleksi snapshot atau langsung IEnumerable<T> (atau subjenisnya) untuk mewakili koleksi yang volatil (yaitu, yang dapat berubah tanpa memodifikasi koleksi secara eksplisit).

Secara umum, semua koleksi yang mewakili sumber daya bersama (misalnya, file dalam direktori) bersifat fluktuatif. Koleksi semacam itu sangat sulit atau tidak mungkin untuk diimplementasikan sebagai koleksi langsung kecuali implementasinya hanyalah pencacahan khusus ke depan.

Memilih Antara Array dan Koleksi

✔️ Lebih suka koleksi daripada array.

Koleksi memberikan kontrol lebih atas konten, dapat berkembang dari waktu ke waktu, dan lebih dapat digunakan. Selain itu, menggunakan array untuk skenario baca-saja tidak dianjurkan karena biaya kloning array adalah penghalang. Studi kegunaan telah menunjukkan bahwa beberapa pengembang merasa lebih nyaman menggunakan API berbasis koleksi.

Namun, jika Anda mengembangkan API tingkat rendah, mungkin lebih baik menggunakan array untuk skenario baca-tulis. Array memiliki jejak memori yang lebih kecil, yang membantu mengurangi set kerja, dan akses ke elemen dalam array lebih cepat karena dioptimalkan oleh runtime.

✔️ PERTIMBANGKAN untuk menggunakan array dalam API tingkat rendah untuk meminimalkan konsumsi memori dan memaksimalkan kinerja.

✔️ DO menggunakan array byte alih-alih koleksi byte.

❌ JANGAN gunakan array untuk properti jika properti harus mengembalikan array baru (misalnya, salinan array internal) setiap kali properti getter dipanggil.

Menerapkan Koleksi Kustom

✔️ PERTIMBANGKAN untuk mewarisi dari Collection<T>, ReadOnlyCollection<T>, atau KeyedCollection<TKey,TItem> saat merancang koleksi baru.

✔️ DO menerapkan IEnumerable<T> saat merancang koleksi baru. Pertimbangkan untuk menerapkan ICollection<T> atau bahkan IList<T> jika itu masuk akal.

Saat menerapkan koleksi kustom tersebut, ikuti pola API yang ditetapkan oleh Collection<T> dan ReadOnlyCollection<T> sedekat mungkin. Artinya, terapkan anggota yang sama secara eksplisit, beri nama parameter seperti dua koleksi ini beri nama mereka, dan sebagainya.

✔️ PERTIMBANGKAN untuk menerapkan antarmuka pengumpulan nongenerik (IList dan ICollection) jika koleksi akan sering diteruskan ke API yang mengambil antarmuka ini sebagai input.

❌ HINDARI menerapkan antarmuka pengumpulan pada jenis dengan API kompleks yang tidak terkait dengan konsep koleksi.

❌ JANGAN mewarisi dari koleksi dasar nongenerik seperti CollectionBase. Kode harus menggunakan Collection<T>, ReadOnlyCollection<T>, dan KeyedCollection<TKey,TItem> sebagai gantinya.

Penamaan Koleksi Kustom

Koleksi (jenis yang mengimplementasikan IEnumerable) dibuat terutama karena dua alasan: (1) untuk membuat struktur data baru dengan operasi khusus struktur dan sering kali karakteristik performa yang berbeda dari struktur data yang ada (misalnya, List<T>, LinkedList<T>, Stack<T>), dan (2) untuk membuat koleksi khusus untuk menyimpan sekumpulan item tertentu (misalnya, StringCollection). Struktur data paling sering digunakan dalam implementasi internal aplikasi dan perpustakaan. Koleksi khusus terutama akan diekspos dalam API (sebagai jenis properti dan parameter).

✔️ DO menggunakan akhiran "Kamus" dalam nama abstraksi yang menerapkan IDictionary atau IDictionary<TKey,TValue>.

✔️ DO menggunakan akhiran "Koleksi" dalam nama jenis yang diimplementasikan IEnumerable (atau salah satu turunannya) dan mewakili daftar item.

✔️ Gunakan nama struktur data yang sesuai untuk struktur data kustom.

❌ AVOID menggunakan akhiran apa pun yang menyiratkan implementasi tertentu, seperti "LinkedList" atau "Hashtable," dalam nama abstraksi koleksi.

✔️ PERTIMBANGKAN awalan nama koleksi dengan nama jenis item. Misalnya, koleksi yang menyimpan item jenis Address (penerapan IEnumerable<Address>) harus diberi nama AddressCollection. Jika jenis item adalah antarmuka, awalan "I" dari jenis item dapat dihilangkan. Dengan demikian, kumpulan IDisposable item dapat disebut DisposableCollection.

✔️ PERTIMBANGKAN untuk menggunakan awalan "ReadOnly" dalam nama koleksi baca-saja jika koleksi yang dapat ditulis yang sesuai mungkin ditambahkan atau sudah ada dalam kerangka kerja.

Misalnya, kumpulan string baca-saja harus disebut ReadOnlyStringCollection.

Portions © 2005, 2009 Microsoft Corporation. Semua hak dilindungi undang-undang.

Dicetak ulang dengan izin dari Pearson Education, Inc. dari Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition oleh Krzysztof Cwalina dan Brad Abrams, diterbitkan 22 Okt 2008 oleh Addison-Wesley Professional sebagai bagian dari Seri Pengembangan Microsoft Windows.

Lihat juga