Seorang rekan kerja hari ini bertanya kepada saya bagaimana cara menambahkan rentang ke koleksi. Dia memiliki kelas yang diwarisi Collection<T>
. Ada properti get-only dari jenis tersebut yang sudah berisi beberapa item. Dia ingin menambahkan item dalam koleksi lain ke koleksi properti. Bagaimana dia bisa melakukannya dengan cara yang ramah C # 3? (Perhatikan batasan tentang properti get-only, yang mencegah solusi seperti melakukan Union dan menetapkan ulang.)
Tentu, kedepan dengan Properti. Tambahkan akan berfungsi. Tapi List<T>
AddRange bergaya akan jauh lebih elegan.
Cukup mudah untuk menulis metode ekstensi:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Tapi saya merasa saya menemukan kembali kemudi. Saya tidak menemukan sesuatu yang serupa di System.Linq
atau morelinq .
Desain yang buruk? Panggil saja Tambahkan? Kehilangan yang sudah jelas?
sumber
ICollection<T>
sepertinya tidak punyaAdd
metode. msdn.microsoft.com/en-us/library/… NamunCollection<T>
punya satu.Add(T item)
di tempat pertama? Sepertinya pendekatan setengah matang untuk menawarkan kemampuan untuk menambahkan satu item dan kemudian mengharapkan semua penelepon untuk mengulang untuk menambahkan lebih dari satu pada satu waktu. Pernyataan Anda memang benar,IEnumerable<T>
tetapi saya mendapati diri saya frustrasiICollections
lebih dari satu kali. Saya tidak setuju dengan Anda, hanya ventilasi.Jawaban:
Tidak, ini sepertinya masuk akal. Ada metode
List<T>.
AddRange () yang pada dasarnya hanya melakukan ini, tetapi mengharuskan koleksi Anda menjadi konkretList<T>
.sumber
Coba transmisikan ke List dalam metode ekstensi sebelum menjalankan loop. Dengan cara itu Anda dapat memanfaatkan kinerja List.AddRange.
sumber
as
Operator tidak akan pernah membuang. Jikadestination
tidak dapat dilemparkan,list
akan menjadi nol danelse
blok akan dieksekusi.if (destination is List<T> list)
Karena
.NET4.5
jika Anda ingin satu baris, Anda dapat menggunakanSystem.Collections.Generic
ForEach.atau bahkan lebih pendek seperti
Dari segi kinerja, itu sama untuk setiap loop (gula sintaksis).
Juga jangan mencoba menetapkannya seperti
penyebabnya
ForEach
batal.Sunting: Disalin dari komentar, pendapat Lipert di ForEach
sumber
ForEach
tampaknya hanya didefinisikan padaList<T>
, bukanCollection
?Ingatlah bahwa masing-masing
Add
akan memeriksa kapasitas koleksi dan mengubah ukurannya kapan pun diperlukan (lebih lambat). DenganAddRange
koleksi akan diatur kapasitasnya dan kemudian ditambahkan item (lebih cepat). Metode ekstensi ini akan sangat lambat, tetapi akan berhasil.sumber
Ini adalah versi yang lebih maju / siap produksi:
sumber
destination
adalah daftarShape
, kelas abstrak.source
adalah daftar dariCircle
, kelas yang diwariskan.Semua kelas C5 Generic Collections Library mendukung
AddRange
metode ini. C5 memiliki antarmuka yang jauh lebih kuat yang benar-benar memperlihatkan semua fitur implementasi yang mendasarinya dan kompatibel dengan antarmuka dengan antarmukaSystem.Collections.Generic
ICollection
danIList
, yang berarti bahwaC5
koleksi dapat dengan mudah diganti sebagai implementasi yang mendasarinya.sumber
Anda dapat menambahkan rentang IEnumerable Anda ke daftar kemudian mengatur ICollection = ke daftar.
sumber
Atau Anda bisa membuat ekstensi ICollection seperti ini:
Menggunakannya akan seperti menggunakannya dalam daftar:
sumber