Saya memiliki properti di kelas yang merupakan ISet. Saya mencoba untuk mendapatkan hasil dari permintaan LINQ ke properti itu, tetapi tidak tahu bagaimana melakukannya.
Pada dasarnya, mencari bagian terakhir ini:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
Bisa juga melakukan ini:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
HashedSet
bagian. Itu hanya membingungkan karenaC#
danLINQ
tidak memiliki apa pun yang disebutHashedSet
.Jawaban:
Saya tidak berpikir ada sesuatu yang dibangun di mana melakukan ini ... tetapi sangat mudah untuk menulis metode ekstensi:
Perhatikan bahwa Anda benar-benar menginginkan metode ekstensi (atau setidaknya metode generik dari beberapa bentuk) di sini, karena Anda mungkin tidak dapat mengekspresikan jenis
T
secara eksplisit:Anda tidak dapat melakukannya dengan panggilan eksplisit ke
HashSet<T>
konstruktor. Kami mengandalkan inferensi jenis untuk metode umum untuk melakukannya bagi kami.Sekarang Anda dapat memilih untuk memberi nama
ToSet
dan kembaliISet<T>
- tapi saya akan tetap denganToHashSet
dan jenis beton. Ini konsisten dengan operator LINQ standar (ToDictionary
,ToList
) dan memungkinkan untuk ekspansi di masa depan (misalnyaToSortedSet
). Anda mungkin juga ingin memberikan kelebihan menentukan perbandingan untuk digunakan.sumber
GetHashCode
danEquals
? Jika tidak, mereka tidak akan jauh lebih baik dalam HashSet ...ForEach
, tetapiToHashSet
jauh lebih masuk akal - Saya tidak tahu alasan untuk tidak melakukanToHashSet
selain dari yang normal "tidak memenuhi bilah kegunaan" (yang saya tidak setuju, tapi saya tidak setuju, tapi ...)Cukup berikan IEnumerable Anda ke konstruktor untuk HashSet.
sumber
bar.Items
akan menjadiT
. Mengingat betapa mudahnya membuat tujuan umum ini, dan seberapa sering tipe anonim muncul di LINQ, saya pikir ada baiknya mengambil langkah tambahan.Fungsi ini telah ditambahkan sebagai metode ekstensi
IEnumerable<TSource>
ke .NET Framework 4.7.2 :ToHashSet<TSource>(IEnumerable<TSource>)
ToHashSet<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
sumber
Seperti yang dikatakan @ Joel, Anda bisa meneruskan enumerable Anda. Jika Anda ingin melakukan metode ekstensi, Anda dapat melakukan:
sumber
Jika Anda hanya perlu akses hanya baca ke set dan sumbernya adalah parameter untuk metode Anda, maka saya akan pergi dengan
Alasannya adalah, bahwa pengguna dapat memanggil metode Anda dengan yang
ISet
sudah jadi Anda tidak perlu membuat salinan.sumber
Ada metode ekstensi yang dibangun dalam kerangka .NET dan inti .NET untuk mengonversikannya
IEnumerable
menjadiHashSet
: https://docs.microsoft.com/en-us/dotnet/api/?term=ToHashSetTampaknya saya belum bisa menggunakannya di .NET standard libraries (saat penulisan). Jadi saya menggunakan metode ekstensi ini:
sumber
Itu cukup sederhana :)
dan ya T adalah tipe yang ditentukan oleh OP :)
sumber
Jawaban Jon sempurna. Satu-satunya peringatan adalah bahwa, menggunakan HashedSet NHibernate, saya perlu mengubah hasilnya menjadi koleksi. Apakah ada cara optimal untuk melakukan ini?
atau
Atau apakah saya melewatkan sesuatu yang lain?
Sunting: Inilah yang akhirnya saya lakukan:
sumber
ToList
umumnya lebih efisien daripadaToArray
. Apakah itu hanya perlu diimplementasikanICollection<T>
?Daripada konversi sederhana dari IEnumerable ke HashSet, sering kali lebih mudah untuk mengubah properti objek lain menjadi HashSet. Anda dapat menulis ini sebagai:
tetapi, preferensi saya adalah menggunakan penyeleksi:
Mereka melakukan hal yang sama, dan yang kedua jelas lebih pendek, tetapi saya menemukan idiom tersebut lebih cocok dengan otak saya (saya menganggapnya seperti ToDictionary).
Inilah metode ekstensi untuk digunakan, dengan dukungan untuk pembanding khusus sebagai bonus.
sumber