.NET menawarkan wadah daftar umum yang kinerjanya hampir sama (lihat pertanyaan Kinerja Array vs. Daftar). Namun mereka sangat berbeda dalam inisialisasi.
Array sangat mudah diinisialisasi dengan nilai default, dan menurut definisi, array sudah memiliki ukuran tertentu:
string[] Ar = new string[10];
Yang memungkinkan seseorang untuk menetapkan item acak dengan aman, katakanlah:
Ar[5]="hello";
dengan daftar hal-hal yang lebih rumit. Saya dapat melihat dua cara untuk melakukan inisialisasi yang sama, yang keduanya tidak akan Anda sebut elegan:
List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);
atau
string[] Ar = new string[10];
List<string> L = new List<string>(Ar);
Apa cara yang lebih bersih?
EDIT: Jawaban sejauh ini mengacu pada kapasitas, yang merupakan sesuatu yang lain selain mengisi daftar. Misalnya, pada daftar yang baru dibuat dengan kapasitas 10 orang, tidak dapat dilakukanL[2]="somevalue"
EDIT 2: Orang-orang bertanya-tanya mengapa saya ingin menggunakan daftar dengan cara ini, karena ini bukan cara yang dimaksudkan untuk digunakan. Saya dapat melihat dua alasan:
Seseorang dapat dengan cukup meyakinkan berpendapat bahwa daftar adalah array "generasi berikutnya", menambahkan fleksibilitas hampir tanpa penalti. Oleh karena itu seseorang harus menggunakannya secara default. Saya menunjukkan bahwa mereka mungkin tidak semudah diinisialisasi.
Apa yang saya tulis saat ini adalah kelas dasar yang menawarkan fungsionalitas default sebagai bagian dari kerangka kerja yang lebih besar. Dalam fungsionalitas default yang saya tawarkan, ukuran List diketahui di tingkat lanjut dan oleh karena itu saya dapat menggunakan array. Namun, saya ingin menawarkan kelas dasar kesempatan untuk memperluasnya secara dinamis dan oleh karena itu saya memilih daftar.
List
bukan penggantiArray
. Mereka memecahkan masalah yang sangat terpisah. Jika Anda menginginkan ukuran tetap, Anda menginginkan fileArray
. Jika Anda menggunakan aList
, Anda Melakukannya dengan Salah.Jawaban:
Saya tidak dapat mengatakan saya sangat membutuhkan ini - dapatkah Anda memberikan detail lebih lanjut tentang mengapa Anda menginginkan ini? Saya mungkin akan meletakkannya sebagai metode statis di kelas helper:
Anda bisa menggunakan
Enumerable.Repeat(default(T), count).ToList()
tetapi itu tidak efisien karena perubahan ukuran buffer.Perhatikan bahwa jika
T
merupakan tipe referensi, itu akan menyimpancount
salinan referensi yang diteruskan untukvalue
parameter - jadi semuanya akan merujuk ke objek yang sama. Itu mungkin atau mungkin tidak yang Anda inginkan, tergantung pada kasus penggunaan Anda.EDIT: Seperti yang disebutkan di komentar, Anda dapat
Repeated
menggunakan loop untuk mengisi daftar jika Anda mau. Itu juga akan sedikit lebih cepat. Secara pribadi saya menemukan kode menggunakanRepeat
lebih deskriptif, dan menduga bahwa di dunia nyata perbedaan kinerja tidak akan relevan, tetapi jarak tempuh Anda mungkin berbeda.sumber
Enumerable.Repeat(...).ToArray()
, yang bukan bagaimana saya menggunakannya.Enumerable.Repeat()
cara berikut (diimplementasikanPair
seperti yang setara dengan C ++):Enumerable.Repeat( new Pair<int,int>(int.MaxValue,-1), costs.Count)
memperhatikan efek sampingnya, bahwaList
itu penuh dengan salinan yang direferensikan ke satu objek. Mengubah elemen sepertimyList[i].First = 1
mengubah setiap elemen secara keseluruhanList
. Butuh waktu berjam-jam untuk menemukan bug ini. Apakah kalian tahu solusi untuk masalah ini (kecuali untuk hanya menggunakan loop umum dan menggunakan.Add(new Pair...)
?sumber
L
hanya akan menggunakan kembali memoristring[10]
sebagaimana adanya (penyimpanan cadangan dari daftar juga merupakan array) atau akan mengalokasikan memori baru sendiri dan kemudian menyalin isinyastring[10]
?string[10]
akan mengumpulkan sampah secara otomatis jikaL
memilih rute selanjutnya.Gunakan konstruktor yang menggunakan int ("capacity") sebagai argumen:
EDIT: Saya harus menambahkan bahwa saya setuju dengan Frederik. Anda menggunakan Daftar dengan cara yang bertentangan dengan seluruh alasan di balik penggunaannya sejak awal.
EDIT2:
Mengapa ada orang yang perlu mengetahui ukuran List dengan semua nilai null? Jika tidak ada nilai riil dalam daftar, saya akan mengharapkan panjangnya menjadi 0. Bagaimanapun, fakta bahwa ini tidak jelas menunjukkan bahwa ini bertentangan dengan tujuan penggunaan kelas.
sumber
new List<string>()
sejauh masalahnya . Bagus sekali untuk mendapatkan begitu banyak suara positif :)list[index] = obj;
dan menggunakan beberapa kemampuan daftar lainnya.Buat array dengan jumlah item yang Anda inginkan terlebih dahulu, lalu konversikan ke dalam List.
sumber
Mengapa Anda menggunakan List jika Anda ingin memulainya dengan nilai tetap? Saya dapat memahami bahwa-demi kinerja- Anda ingin memberikannya kapasitas awal, tetapi bukankah salah satu keuntungan dari list dibandingkan dengan array biasa yang dapat bertambah saat dibutuhkan?
Saat Anda melakukan ini:
Anda membuat daftar yang kapasitasnya 100 bilangan bulat. Ini berarti List Anda tidak perlu 'bertambah' sampai Anda menambahkan item ke-101. Array yang mendasari daftar akan diinisialisasi dengan panjang 100.
sumber
Menginisialisasi konten daftar seperti itu bukanlah tujuan daftar. Daftar dirancang untuk menampung objek. Jika Anda ingin memetakan nomor tertentu ke objek tertentu, pertimbangkan untuk menggunakan struktur pasangan nilai-kunci seperti tabel atau kamus hash daripada daftar.
sumber
Anda tampaknya menekankan perlunya asosiasi posisi dengan data Anda, jadi bukankah array asosiatif lebih cocok?
sumber
Jika Anda ingin menginisialisasi daftar dengan N elemen dari beberapa nilai tetap:
sumber
Anda dapat menggunakan Linq untuk secara cerdik menginisialisasi daftar Anda dengan nilai default. (Mirip dengan jawaban David B. )
Selangkah lebih maju dan inisialisasi setiap string dengan nilai berbeda "string 1", "string 2", "string 3", dll:
sumber
sumber
Jawaban yang diterima (yang memiliki tanda centang hijau) bermasalah.
Masalah:
Saya merekomendasikan mengubah baris di atas untuk melakukan salinan objek. Ada banyak artikel berbeda tentang itu:
Jika Anda ingin menginisialisasi setiap item dalam daftar Anda dengan konstruktor default, daripada NULL, tambahkan metode berikut:
sumber
Pemberitahuan tentang IList: MSDN IList Keterangan : "Penerapan IList terbagi dalam tiga kategori: hanya baca, ukuran tetap, dan ukuran variabel. (...). Untuk versi umum antarmuka ini, lihat
System.Collections.Generic.IList<T>
."IList<T>
TIDAK mewarisi dariIList
(tetapiList<T>
menerapkan keduanyaIList<T>
danIList
), tetapi selalu berukuran variabel . Sejak .NET 4.5, kami juga memilikiIReadOnlyList<T>
AFAIK, tidak ada List generik berukuran tetap yang akan menjadi apa yang Anda cari.sumber
Ini adalah sampel yang saya gunakan untuk pengujian unit saya. Saya membuat daftar objek kelas. Kemudian saya menggunakan forloop untuk menambahkan jumlah 'X' objek yang saya harapkan dari layanan. Dengan cara ini Anda dapat menambahkan / menginisialisasi List untuk ukuran tertentu.
Semoga saya bisa membantu kalian.
sumber
Agak terlambat tetapi solusi pertama yang Anda usulkan tampaknya jauh lebih bersih bagi saya: Anda tidak mengalokasikan memori dua kali. Bahkan pembuat Daftar perlu mengulang melalui array untuk menyalinnya; Ia bahkan tidak tahu sebelumnya hanya ada elemen nol di dalamnya.
1. - alokasikan N - loop N Biaya: 1 * alokasikan (N) + N * loop_iteration
2. - alokasikan N - alokasikan N + loop () Biaya: 2 * alokasikan (N) + N * loop_iteration
Namun alokasi List, loop mungkin lebih cepat karena List adalah kelas built-in, tetapi C # dikompilasi dengan jit sooo ...
sumber