MyClass[] array;
List<MyClass> list;
Apa skenario ketika satu lebih disukai daripada yang lain? Dan mengapa?
MyClass[] array;
List<MyClass> list;
Apa skenario ketika satu lebih disukai daripada yang lain? Dan mengapa?
Jawaban:
Jarang, pada kenyataannya, Anda ingin menggunakan array. Pasti menggunakan waktu List<T>kapan saja Anda ingin menambah / menghapus data, karena mengubah ukuran array mahal. Jika Anda tahu datanya panjang tetap, dan Anda ingin mengoptimalkan mikro untuk beberapa alasan yang sangat spesifik (setelah benchmarking), maka sebuah array mungkin berguna.
List<T>menawarkan lebih banyak fungsionalitas daripada sebuah array (walaupun LINQ sedikit meratakannya), dan hampir selalu merupakan pilihan yang tepat. Kecuali untuk paramsargumen, tentu saja. ;-p
Sebagai penghitung - List<T>adalah satu dimensi; di mana-seperti Anda memiliki array persegi panjang (dll) seperti int[,]atau string[,,]- tetapi ada cara lain untuk memodelkan data tersebut (jika Anda perlu) dalam model objek.
Lihat juga:
Yang mengatakan, saya menggunakan banyak array dalam proyek protobuf-net saya ; sepenuhnya untuk kinerja:
byte[]sangat penting untuk encoding;byte[]buffer lokal yang saya isi sebelum mengirim ke aliran yang mendasarinya (dan vv); lebih cepat dari BufferedStreamdll;Foo[]bukan List<Foo>), karena ukurannya diperbaiki setelah dibangun, dan harus sangat cepat.Tapi ini jelas pengecualian; untuk pemrosesan lini bisnis umum, List<T>setiap kali menang.
Benar-benar hanya menjawab untuk menambahkan tautan yang saya terkejut belum disebutkan: entri blog Eric Lippert di "Array dianggap agak berbahaya."
Anda dapat menilai dari judul yang disarankan menggunakan koleksi di mana pun praktis - tetapi seperti yang ditunjukkan Marc dengan tepat, ada banyak tempat di mana array benar-benar merupakan satu-satunya solusi praktis.
Terlepas dari jawaban lain yang merekomendasikan List<T>, Anda harus menggunakan array saat menangani:
List<T>array di sini daripada byte?
Kecuali jika Anda benar-benar peduli dengan kinerja, dan maksud saya, "Mengapa Anda menggunakan .Net, bukan C ++?" Anda harus tetap menggunakan List <>. Lebih mudah untuk mempertahankan dan melakukan semua pekerjaan kotor mengubah ukuran array di belakang layar untuk Anda. (Jika perlu, Daftar <> cukup pintar dalam memilih ukuran array sehingga tidak perlu biasanya.)
Array harus digunakan dalam preferensi ke Daftar ketika imutabilitas koleksi itu sendiri adalah bagian dari kontrak antara kode klien & penyedia (tidak harus immutabilitas item dalam koleksi) DAN ketika IEnumerable tidak cocok.
Sebagai contoh,
var str = "This is a string";
var strChars = str.ToCharArray(); // returns array
Jelas bahwa modifikasi "strChars" tidak akan bermutasi objek "str" asli, terlepas dari pengetahuan tingkat implementasi dari tipe "str" yang mendasarinya.
Tapi anggap itu
var str = "This is a string";
var strChars = str.ToCharList(); // returns List<char>
strChars.Insert(0, 'X');
Dalam kasus ini, tidak jelas hanya dari snipet kode itu jika metode penyisipan akan atau tidak akan bermutasi objek "str" asli. Dibutuhkan pengetahuan tingkat implementasi dari String untuk membuat tekad itu, yang mematahkan pendekatan Design by Contract. Dalam kasus String, ini bukan masalah besar, tetapi bisa menjadi masalah besar di hampir setiap kasus lainnya. Mengatur Daftar hanya-baca tidak membantu tetapi menghasilkan kesalahan run-time, bukan waktu kompilasi.
Toakan membuat objek yang tidak memiliki kemampuan untuk mengubah contoh asli, yang bertentangan dengan strChars as char[]yang jika valid akan menyarankan Anda sekarang dapat memodifikasi objek asli.
strinternal menggunakan array dan ToCharArraymengembalikan referensi ke array ini maka klien dapat bermutasi strdengan mengubah elemen-elemen array itu, bahkan jika ukurannya tetap. Namun Anda menulis 'Jelas bahwa modifikasi "strChars" tidak akan mengubah objek "str" yang asli. Apa yang kulewatkan di sini? Dari apa yang saya lihat, dalam kedua kasus klien dapat memiliki akses ke representasi internal dan, terlepas dari jenisnya, ini akan memungkinkan mutasi dari beberapa jenis.
Sebagian besar waktu, menggunakan Listakan cukup. A Listmenggunakan larik internal untuk menangani datanya, dan secara otomatis mengubah ukuran larik saat menambahkan lebih banyak elemen Listdaripada kapasitas saat ini, yang membuatnya lebih mudah digunakan daripada larik, di mana Anda perlu mengetahui kapasitasnya sebelumnya.
Lihat http://msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx#datastructures20_1_topic5 untuk informasi lebih lanjut tentang Daftar di C # atau hanya mendekompilasi System.Collections.Generic.List<T>.
Jika Anda membutuhkan data multidimensi (misalnya menggunakan matriks atau dalam pemrograman grafis), Anda mungkin akan memilih yang arraysebaliknya.
Seperti biasa, jika memori atau kinerja bermasalah, ukurlah! Kalau tidak, Anda bisa membuat asumsi yang salah tentang kode.
Array Vs. Daftar adalah masalah rawatan klasik vs. kinerja. Aturan praktis yang diikuti oleh hampir semua pengembang adalah Anda harus menembak untuk keduanya, tetapi ketika mereka mengalami konflik, pilihlah rawatan daripada kinerja. Pengecualian untuk aturan itu adalah ketika kinerja telah terbukti menjadi masalah. Jika Anda membawa prinsip ini ke Array Vs. Daftar, lalu yang Anda dapatkan adalah ini:
Gunakan daftar yang sangat diketik sampai Anda menekan masalah kinerja. Jika Anda mengalami masalah kinerja, buat keputusan apakah drop out ke array akan menguntungkan solusi Anda dengan kinerja lebih daripada itu akan merugikan solusi Anda dalam hal pemeliharaan.
Situasi lain yang belum disebutkan adalah ketika seseorang akan memiliki sejumlah besar item, yang masing-masing terdiri dari sekelompok variabel terkait-tetapi-independen yang saling menempel (mis. Koordinat suatu titik, atau simpul dari segitiga 3d). Susunan struktur bidang terbuka akan memungkinkan elemen-elemennya dimodifikasi secara efisien "di tempat" - sesuatu yang tidak mungkin dilakukan dengan jenis koleksi lainnya. Karena array struktur memegang elemen-elemennya secara berurutan dalam RAM, akses berurutan ke elemen array bisa sangat cepat. Dalam situasi di mana kode perlu membuat banyak melewati sekuensial melalui array, array struktur dapat mengungguli array atau kumpulan referensi objek kelas lainnya dengan faktor 2: 1; lebih lanjut,
Meskipun array tidak dapat diubah ukurannya, tidak sulit untuk memiliki kode yang menyimpan referensi array bersama dengan jumlah elemen yang digunakan, dan mengganti array dengan yang lebih besar sesuai kebutuhan. Atau, seseorang dapat dengan mudah menulis kode untuk tipe yang berperilaku seperti List<T>tetapi membuka backing store-nya, sehingga memungkinkan seseorang untuk mengatakan salah satu MyPoints.Add(nextPoint);atau MyPoints.Items[23].X += 5;. Perhatikan bahwa yang terakhir tidak perlu membuang pengecualian jika kode mencoba mengakses di luar akhir daftar, tetapi penggunaan sebaliknya akan sangat mirip secara konseptual List<T>.
Point[] arr;, mungkin untuk kode mengatakan, misalnya arr[3].x+=q;. Menggunakan misalnya List<Point> list, akan perlu untuk mengatakan sebaliknya Point temp=list[3]; temp.x+=q; list[3]=temp;. Akan sangat membantu jika List<T>punya metode Update<TP>(int index, ActionByRefRef<T,TP> proc, ref TP params). dan kompiler bisa berubah list[3].x+=q;menjadi {list.Update(3, (ref int value, ref int param)=>value+=param, ref q);tetapi tidak ada fitur seperti itu.
list[0].X += 3;akan menambahkan 3 ke properti X dari elemen pertama dari daftar. Dan listadalah List<Point>dan Pointmerupakan kelas dengan sifat X dan Y
Daftar di .NET adalah pembungkus di atas array, dan menggunakan array secara internal. Kompleksitas waktu operasi pada daftar adalah sama dengan array, namun ada sedikit biaya tambahan dengan semua fungsionalitas tambahan / kemudahan penggunaan daftar (seperti pengubahan ukuran otomatis dan metode yang disertakan dengan kelas daftar). Cukup banyak, saya akan merekomendasikan menggunakan daftar dalam semua kasus kecuali ada alasan kuat untuk tidak melakukannya, seperti jika Anda perlu menulis kode yang sangat optimal, atau bekerja dengan kode lain yang dibangun di sekitar array.
Daripada melakukan perbandingan fitur dari masing-masing tipe data, saya pikir jawaban yang paling pragmatis adalah "perbedaan mungkin tidak begitu penting untuk apa yang perlu Anda capai, terutama karena keduanya diterapkan IEnumerable, jadi ikuti konvensi populer dan gunakan Listsampai Anda memiliki alasan untuk tidak, pada titik mana Anda mungkin akan memiliki alasan untuk menggunakan array di atas List. "
Sebagian besar waktu dalam kode terkelola Anda akan ingin mendukung koleksi menjadi semudah mungkin untuk dikerjakan karena terlalu khawatir tentang optimasi mikro.
Mereka mungkin tidak populer, tapi saya penggemar Array dalam proyek game. - Kecepatan Iterasi dapat menjadi penting dalam beberapa kasus, karena pada suatu Array memiliki overhead yang jauh lebih sedikit jika Anda tidak melakukan banyak per elemen - Menambah dan menghapus tidak begitu sulit dengan fungsi pembantu - Lebih lambat, tetapi dalam kasus di mana Anda hanya membangunnya sekali itu mungkin tidak masalah - Dalam kebanyakan kasus, memori ekstra kurang terbuang (hanya benar-benar signifikan dengan Array struct) - Sedikit lebih sedikit sampah dan pointer dan pengejaran pointer
Yang sedang berkata, saya menggunakan Daftar jauh lebih sering daripada Array dalam praktek, tetapi mereka masing-masing memiliki tempat masing-masing.
Akan lebih baik jika Daftar di mana tipe built in sehingga mereka dapat mengoptimalkan pembungkus dan overhead enumerasi.
Mengisi daftar lebih mudah daripada array. Untuk array, Anda perlu mengetahui panjang data yang tepat, tetapi untuk daftar, ukuran data bisa berapa saja. Dan, Anda dapat mengubah daftar menjadi array.
List<URLDTO> urls = new List<URLDTO>();
urls.Add(new URLDTO() {
key = "wiki",
url = "https://...",
});
urls.Add(new URLDTO()
{
key = "url",
url = "http://...",
});
urls.Add(new URLDTO()
{
key = "dir",
url = "https://...",
});
// convert a list into an array: URLDTO[]
return urls.ToArray();
Karena tidak ada yang menyebutkan: Dalam C #, array adalah daftar. MyClass[]dan List<MyClass>keduanya mengimplementasikan IList<MyClass>. (mis. void Foo(IList<int> foo)bisa disebut suka Foo(new[] { 1, 2, 3 })atau Foo(new List<int> { 1, 2, 3 }))
Jadi, jika Anda menulis metode yang menerima List<MyClass>argumen, tetapi hanya menggunakan subset fitur, Anda mungkin ingin mendeklarasikan sebagai IList<MyClass>gantinya untuk kenyamanan penelepon.
Detail:
List, hanya mengimplementasikan IListantarmuka.
Ini sepenuhnya tergantung pada konteks di mana struktur data diperlukan. Misalnya, jika Anda membuat item untuk digunakan oleh fungsi atau layanan lain menggunakan Daftar adalah cara sempurna untuk mencapainya.
Sekarang jika Anda memiliki daftar item dan Anda hanya ingin menampilkannya, katakanlah pada array halaman web adalah wadah yang perlu Anda gunakan.
IEnumerable<T>- maka saya dapat melakukan streaming objek daripada buffer mereka.
Perlu disebutkan tentang kemampuan melakukan casting di tempat.
interface IWork { }
class Foo : IWork { }
void Test( )
{
List<Foo> bb = new List<Foo>( );
// Error: CS0029 Cannot implicitly convert type 'System.Collections.Generic.List<Foo>' to 'System.Collections.Generic.List<IWork>'
List<IWork> cc = bb;
Foo[] bbb = new Foo[4];
// Fine
IWork[] ccc = bbb;
}
Jadi Array menawarkan sedikit lebih banyak fleksibilitas ketika digunakan dalam tipe pengembalian atau argumen untuk fungsi.
IWork[] GetAllWorks( )
{
List<Foo> fooWorks = new List<Foo>( );
return fooWorks.ToArray( ); // Fine
}
void ExecuteWorks( IWork[] works ) { } // Also accept Foo[]