Pertanyaan saya sebagai judul di atas. Sebagai contoh,
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
tapi bagaimanapun juga hanya ada 1 item di dalamnya.
Bisakah kita memiliki metode seperti items.Add(item)
?
seperti List<T>
c#
list
ienumerable
Lihat sekarang
sumber
sumber
IEnumerable<T>
dimaksudkan untuk menanyakan koleksi saja. Ini adalah tulang punggung kerangka kerja LINQ. Ini selalu merupakan abstraksi dari beberapa koleksi lain sepertiCollection<T>
,List<T>
, atauArray
. Antarmuka hanya menyediakanGetEnumerator
metode yang mengembalikan instanceIEnumerator<T>
yang memungkinkan berjalannya koleksi yang diperluas satu per satu. Metode ekstensi LINQ dibatasi oleh antarmuka ini.IEnumerable<T>
dirancang untuk dibaca hanya karena dapat mewakili agregasi bagian dari beberapa koleksi.IList<T>
alih-alihIEnumerable<T>
:IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2"));
Jawaban:
Anda tidak bisa, karena
IEnumerable<T>
tidak selalu mewakili koleksi yang itemnya dapat ditambahkan. Bahkan, itu tidak selalu mewakili koleksi sama sekali! Sebagai contoh:Apa yang dapat Anda lakukan, bagaimanapun, adalah membuat objek baru
IEnumerable
(dari tipe yang tidak ditentukan), yang, ketika disebutkan, akan menyediakan semua item dari yang lama, ditambah beberapa milik Anda sendiri. Anda gunakanEnumerable.Concat
untuk itu:Ini tidak akan mengubah objek array (toh, Anda tidak bisa memasukkan item ke array). Tapi itu akan membuat objek baru yang akan mendaftar semua item dalam array, dan kemudian "Foo". Selain itu, objek baru itu akan melacak perubahan dalam array (yaitu, setiap kali Anda menghitungnya, Anda akan melihat nilai item saat ini).
sumber
Concat
dipanggil berulang kali; dan jika ya, Anda memiliki masalah yang lebih besar, karena setiap kali AndaConcat
, Anda mendapatkan satu lapis enumerator lagi - jadi pada akhirnya itu satu panggilan untukMoveNext
akan menghasilkan rantai panggilan yang sama panjangnya dengan jumlah iterasi.IEnumerable<T>
di C #, termasuk overloadingoperator+
sepertiConcat
(by the way, apakah Anda tahu bahwa dalam VB, Anda dapat indeksIEnumerable
seolah-olah itu sebuah array - menggunakanElementAt
bawah tenda): connect.microsoft.com / VisualStudio / umpan balik / ... . Jika kita juga mendapatkan dua kelebihanConcat
untuk mengambil satu item baik di kiri dan di kanan, ini akan mengurangi pengetikan kexs +=x
- jadi tusuk Mads (Torgersen) untuk memprioritaskan ini dalam C # 5.0 :)Jenis
IEnumerable<T>
ini tidak mendukung operasi semacam itu. TujuanIEnumerable<T>
antarmuka adalah untuk memungkinkan konsumen untuk melihat konten koleksi. Tidak mengubah nilai.Ketika Anda melakukan operasi seperti .ToList (). Add () Anda membuat yang baru
List<T>
dan menambahkan nilai ke daftar itu. Tidak memiliki koneksi ke daftar asli.Yang dapat Anda lakukan adalah menggunakan metode Tambahkan ekstensi untuk membuat yang baru
IEnumerable<T>
dengan nilai tambah.Bahkan dalam kasus ini tidak akan memodifikasi
IEnumerable<T>
objek asli . Ini dapat diverifikasi dengan memegang referensi untuk itu. Sebagai contohSetelah rangkaian operasi ini, temp variabel akan tetap hanya merujuk enumerable dengan elemen tunggal "foo" di set nilai sementara item akan merujuk enumerable berbeda dengan nilai "foo" dan "bar".
EDIT
Saya terus-menerus lupa bahwa Add bukan metode ekstensi biasa
IEnumerable<T>
karena itu adalah salah satu yang pertama yang akhirnya saya definisikan. Ini diasumber
Concat
:)Add
, karenaAdd
pada hampir semua jenis NET lainnya. (Bukan hanya koleksi) bermutasi koleksi di tempat. MungkinWith
? Atau bahkan bisa jadi hanya kelebihan bebanConcat
.Concat
overload mungkin akan menjadi pilihan yang lebih baik karenaAdd
biasanya menyiratkan kemampuan berubah-ubah.return e.Concat(Enumerable.Repeat(value,1));
?Sudahkah Anda mempertimbangkan untuk menggunakan
ICollection<T>
atauIList<T>
antarmuka, mereka ada karena alasan yang Anda ingin memilikiAdd
metode padaIEnumerable<T>
.IEnumerable<T>
digunakan untuk 'menandai' suatu jenis sebagai ... yah, dapat dihitung atau hanya urutan item tanpa harus membuat jaminan apakah objek yang sebenarnya mendasari mendukung penambahan / penghapusan item. Juga ingat bahwa antarmuka ini diimplementasikanIEnumerable<T>
sehingga Anda mendapatkan semua metode ekstensi yang Anda dapatkanIEnumerable<T>
juga.sumber
Pasangan pendek, metode ekstensi manis
IEnumerable
danIEnumerable<T>
lakukan untuk saya:Elegan (well, kecuali untuk versi non-generik). Sayang sekali metode ini tidak ada dalam BCL.
sumber
ToString()
di atasnya, karena itu menangkap lebih banyak detail kesalahan. Saya kira Anda tidakinclude System.Linq;
di bagian atas file Anda, tetapi siapa yang tahu? Cobalah mengatasinya sendiri, buat prototipe minimum yang menunjukkan kesalahan yang sama jika Anda tidak bisa dan kemudian minta bantuan dalam sebuah pertanyaan.Di .net Core, ada metode
Enumerable.Append
yang melakukan hal itu.Kode sumber metode ini tersedia di GitHub. .... Implementasinya (lebih canggih dari saran di jawaban lain) patut dilihat :).
sumber
Tidak, IEnumerable tidak mendukung penambahan item ke dalamnya.
'Alternatif' Anda adalah:
sumber
Untuk menambahkan pesan kedua, Anda perlu -
sumber
Anda tidak hanya tidak dapat menambahkan item seperti yang Anda nyatakan, tetapi jika Anda menambahkan item ke
List<T>
(atau hampir semua koleksi non-baca saja) yang Anda miliki untuk enumerator yang ada, enumerator tidak valid (melemparInvalidOperationException
sejak saat itu).Jika Anda menggabungkan hasil dari beberapa jenis kueri data, Anda dapat menggunakan
Concat
metode ekstensi:Sunting: Saya awalnya menggunakan
Union
ekstensi dalam contoh, yang tidak terlalu benar. Aplikasi saya menggunakannya secara luas untuk memastikan pertanyaan yang tumpang tindih tidak menduplikasi hasil.sumber
Saya hanya datang ke sini untuk mengatakan bahwa, selain dari
Enumerable.Concat
metode ekstensi, tampaknya ada metode lain bernamaEnumerable.Append
.NET Core 1.1.1. Yang terakhir memungkinkan Anda untuk menggabungkan satu item ke urutan yang ada. Jadi jawaban Aamol juga bisa ditulis sebagaiNamun, harap dicatat bahwa fungsi ini tidak akan mengubah urutan input, itu hanya mengembalikan pembungkus yang menempatkan urutan yang diberikan dan item yang ditambahkan bersama-sama.
sumber
Orang lain telah memberikan penjelasan yang bagus tentang mengapa Anda tidak dapat (dan seharusnya tidak!) Dapat menambahkan item ke
IEnumerable
. Saya hanya akan menambahkan bahwa jika Anda ingin melanjutkan pengkodean ke antarmuka yang mewakili koleksi dan ingin metode add, Anda harus kode keICollection
atauIList
. Sebagai tambahan, antarmuka ini mengimplementasikanIEnumerable
.sumber
kamu bisa melakukan ini.
sumber
Cara termudah untuk melakukannya adalah sederhana
Kemudian Anda dapat mengembalikan daftar sebagai IEnumerable juga karena mengimplementasikan antarmuka IEnumerable
sumber
Jika Anda membuat objek
IEnumerable<int> Ones = new List<int>();
Anda maka Anda dapat melakukannya((List<int>)Ones).Add(1);
sumber
Tentu, Anda bisa (saya mengesampingkan bisnis-T Anda):
sumber