Mam właściwość klasy, która jest ISet. Próbuję uzyskać wyniki zapytania linq w tej właściwości, ale nie mogę wymyślić, jak to zrobić.
Zasadniczo, szukając ostatniej części tego:
ISet<T> foo = new HashedSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
Mógłby to również zrobić:
HashSet<T> foo = new HashSet<T>();
foo = (from x in bar.Items select x).SOMETHING;
HashedSet
część. Jest to po prostu myląceC#
i odtądLINQ
nic nie maHashedSet
.Odpowiedzi:
Nie sądzę, żeby było w tym coś wbudowanego ... ale bardzo łatwo jest napisać metodę rozszerzenia:
Zauważ, że naprawdę potrzebujesz tutaj metody rozszerzenia (lub przynajmniej ogólnej metody jakiejś formy), ponieważ możesz nie być w stanie wyrazić typu
T
jawnie:Nie możesz tego zrobić za pomocą jawnego wywołania
HashSet<T>
konstruktora. W tym celu opieramy się na wnioskowaniu o typ dla metod ogólnych.Teraz już mógł wybrać, aby go wymienić
ToSet
i powrótISet<T>
- ale będę trzymaćToHashSet
i rodzaju betonu. Jest to zgodne ze standardowymi operatorami LINQ (ToDictionary
,ToList
) i umożliwia przyszłą rozbudowę (npToSortedSet
.). Możesz także podać przeciążenie określające porównanie do użycia.źródło
GetHashCode
iEquals
? Jeśli nie, nie będą zbyt dobre w HashSet ...ForEach
, aleToHashSet
ma o wiele więcej sensu - nie znam żadnego powodu, aby nie robićToHashSet
inaczej niż normalne „nie spełnia paska użyteczności” (z czym nie chciałbym się zgodzić, ale ...)Po prostu przekaż swój IEnumerable do konstruktora dla HashSet.
źródło
bar.Items
będzieT
. Biorąc pod uwagę, jak łatwo jest osiągnąć ten ogólny cel i jak często anonimowe typy pojawiają się w LINQ, myślę, że warto zrobić dodatkowy krok.Ta funkcjonalność została dodana jako metoda rozszerzenia
IEnumerable<TSource>
do .NET Framework 4.7.2 :ToHashSet<TSource>(IEnumerable<TSource>)
ToHashSet<TSource>(IEnumerable<TSource>, IEqualityComparer<TSource>)
źródło
Jak stwierdził @Joel, możesz po prostu przekazać swoje wyliczenie. Jeśli chcesz zastosować metodę rozszerzenia, możesz:
źródło
Jeśli potrzebujesz tylko dostępu do zestawu tylko do odczytu, a źródło jest parametrem twojej metody, to wybrałbym
Powodem jest to, że użytkownicy mogą wywołać twoją metodę z
ISet
już, więc nie musisz tworzyć kopii.źródło
Istnieje metoda rozszerzenia wbudowana w środowisko .NET i .NET core do konwersji
IEnumerable
naHashSet
: https://docs.microsoft.com/en-us/dotnet/api/?term=ToHashSetWygląda na to, że nie mogę go jeszcze używać w standardowych bibliotekach .NET (w momencie pisania). Więc używam tej metody rozszerzenia:
źródło
To całkiem proste :)
i tak T jest typem określonym przez OP :)
źródło
Odpowiedź Jona jest idealna. Jedynym zastrzeżeniem jest to, że używając HashedSet NHibernate'a muszę przekonwertować wyniki na kolekcję. Czy istnieje optymalny sposób to zrobić?
lub
A może brakuje mi czegoś innego?
Edycja: Właśnie to skończyłem:
źródło
ToList
jest ogólnie bardziej wydajny niżToArray
. Czy to wystarczy wdrożyćICollection<T>
?Zamiast zwykłej konwersji IEnumerable na HashSet, często wygodnie jest przekonwertować właściwość innego obiektu na HashSet. Możesz to napisać jako:
ale wolę używać selektorów:
Robią to samo, a druga jest oczywiście krótsza, ale uważam, że ten idiom lepiej pasuje do moich mózgów (myślę, że to jak ToDictionary).
Oto metoda rozszerzenia, której należy użyć, ze wsparciem dla niestandardowych programów porównujących jako bonusu.
źródło